This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-26
Channels
- # aleph (5)
- # announcements (9)
- # beginners (115)
- # boot (36)
- # calva (13)
- # cider (4)
- # clara (7)
- # cljs-dev (27)
- # cljsrn (20)
- # clojure (182)
- # clojure-conj (3)
- # clojure-dev (4)
- # clojure-europe (3)
- # clojure-italy (2)
- # clojure-nl (4)
- # clojure-uk (34)
- # clojurebridge (3)
- # clojurescript (19)
- # clojureverse-ops (3)
- # core-typed (1)
- # cursive (12)
- # data-science (3)
- # datomic (16)
- # emacs (9)
- # events (5)
- # figwheel-main (11)
- # fulcro (14)
- # graphql (7)
- # jobs (10)
- # jobs-discuss (6)
- # lein-figwheel (8)
- # leiningen (2)
- # lumo (22)
- # mount (1)
- # nrepl (7)
- # off-topic (69)
- # overtone (17)
- # pathom (3)
- # quil (1)
- # re-frame (5)
- # reagent (23)
- # reitit (6)
- # remote-jobs (1)
- # rewrite-clj (4)
- # ring (38)
- # shadow-cljs (54)
- # sql (9)
- # uncomplicate (5)
- # xtdb (1)
what's the best data structure for expressing a bijective map? A <-> B
where the elements within A and B are unique but could overlap
I could maintain two separate hashmaps A -> B
and B ->A
which are inverse of each other, but that seems expensive and error prone.
constantly calling map-invert
on a large map doesn't sound good, I'm concerned about the performance because I'll be using both forward and backwards mappings in a tight inner loop
you can try #(into % (map (juxt val key)) %)
But if you need to access you data from many ways, may be a good idea use #datascript
Thanks! A full database is perhaps too heavy for my needs, I'm just trying to express a bijective mapping / isomorphism between two sets
It needs to be frequently updated in an inner loop, so I can't be constantly regenerating the inverse mapping, and some sort of persistent data sharing would be good
"Full database is too heavy"
datascript subtitle:
What if creating a database would be as cheap as creating a Hashmap?
😝
https://gist.github.com/semperos/3835417 Just found this implementation based on two synchronized maps 🙂
I’m having some issue with the use of pprint/cl-format
throwing an exception when run from an uberjar: ClassCastException clojure.pprint.pfroxy$java.io.Writer$IDeref$PrettyFlush$4923d848 cannot be cast to clojure.pprint.PrettyFlush
; anyone run into this and know how to resolve? (pprint require’d via (:require [clojure.pprint :as pprint])
)
Looks vaguely familiar, likely something reloading causing Pretty Flush to be redefined, so it is a new different class that doesn't match the proxy class
Seems it was related to some timestamp issue in uberjars; updating to a more recent juxt/pack.alpha
seems to have fixed it
I ran into a similar problem with depstar
until I fixed in my fork. The obvious default way of building JAR files is wrong. Who knew? 😞
is there any library that when i add deps in lein project.clj and it auto reload it so that i needn’t restart the repl?
@haiyuan.vinurs Boot lets you add dependencies to the REPL while you're working (using Pomegranate under the hood I think). The Clojure CLI is built on tools.deps
and there's a branch of that which supports an add-lib
function to add new dependencies dynamically. I have an alias for that in my deps.edn
file.
Is there a way to start a program, like using lein run
, but also start nrepl in the background?
Something like https://github.com/jimbru/lein-repl-run does, but without a plugin.
are there any cool clients built around datafy and nav yet? (besides rebl)
@markx lein run myns.dev
where src/myns/dev.clj
contains something like
(ns myns.dev
(:require [nrepl.server :as nrepl]
[myns.core :as core]))
(defn -main
[& args]
(nrepl/start-server 3333)
(apply core/-main args))
@souenzzo Thanks! This is what I’m currently doing. Just curious if there’s a better way.
I spent quite some time learning what lein run
and lein repl
do before getting anything done. 😅
@markx my myns.dev
from the current project do:
- start a #pedestal server (main app)
- start a #nrepl server
- run "yarn install"
- start a #shadow-cljs server
- start ~3 builds in shadow-cljs server
- run a "yarn watch" command "forever"
that about: you will need to start/stop things, maybe in some order, and you dont need to develop a plugin to do it 🙂
Now I have a simple TUI app, and I just added a nrepl server to it. Maybe later I’ll have to add a repl too.
You don't need to prefer
Both have one optimal use-case
I deliver a product that my client require that java -jar app.jar
will work, it's way easier to do with lein
But what I'm saying is that you dont need plugins.
I’m trying to use grpc and protobufs with lein-protoc
and I do get the simplest hello world thing working.
I don’t understand how to include dependencies tho - our company protobufs use com.google.api.grpc/google-apis-common-protos
for example and I can’t seem to include them for lein-proto
looks like it tries to find the relevant jar among the classpath, for each of the given source-deps
so I'd try to make sure your jar is in the classpath first (e.g. as an ordinary dep), then name it in source-deps
There’s a https://github.com/LiaisonTechnologies/lein-protoc#usage :proto-source-deps
vector but I don’t get how I point it to a jar
I’m going through some clojure homework that is proving beyond me, would anybody be able to assist?
@darclan28 why don't you just ask an actual question about clojure so we can brainstorm it together?
Sounds good
This is in a Koans form
given…
(defn empty-set
"takes any input element and returns nil"
[_] nil)
(defn singleton-set
"takes an element and returns a fun-set containing
just that element"
[el1]
(fn [el2]
(when (= el2 el1) el2)))
complete the following…
(defn union
"takes two fun-sets and returns a set that is the set
of all elements in either set1 or set2."
[f-set1 f-set2]
;;TODO
)
so first create two sets
(def f-set1 (singleton-set :happy))
(def f-set2 (singleton-set :sad))
I tried
(def u-set (singleton-set f-set1 f-set2))
just to see what would happengot wrong number of arguments as expected
see above
@darclan28 if i understand it correctly, singleton set can be described as a = singleton set of a
That sounds correct
If I interpret the function in the sample correctly, it will re-assign a new value but keep the original value if identical, which sounds unnecessary
checking
@darclan28 well we describing singleton set, not a pair right?
No, the “fun set” idea is a function that returns a truthy value for elements that are members of the set.
so the union of two singleton sets should be a function that returns a truthy value if the given element is either a member of the first singleton set, or a member of the second.
@darclan28 You’re going to need to write a defn
that returns an fn
. The fn
needs to take one element and return nil
if the element is not a member of either singleton set, or the element itself as a “truthy” result, if it is in either set.
That sounds like verification of contents in multiple sets, But not the combining of two sets into a single set
"takes two fun-sets and returns a set that is the set
of all elements in either set1 or set2."
So here is a contains for a single fun set
(defn f-contains?
"takes an fun set and el and returns true only if that
elements exists in the fun set else false"
[f-set el]
(= (nil? (f-set el)) false)
)
(defn empty-set
"takes any input element and returns nil"
[_] nil)
(defn singleton-set
"takes an element and returns a fun-set containing
just that element"
[element]
(fn [target]
(when (= element target)
target)))
(defn union
"takes two fun-sets and returns a set that is the set
of all elements in either set1 or set2."
[x y]
(fn [target]
(or (x target)
(y target))))
the definition of a singleton set in this exercise is a membership function. In this exercise a set is merely a function that recognizes membership
need to pass false not false nil
in test
FAIL in (union-test) (core_test.clj:44)
true false sets
expected: (= false (u-set1 false))
actual: (not (= false nil))
So that answer, using or, is there a book or site that goes over this kind of topic? It doesn’t feel intuitive to me.
I’d be happy to go over a reading assignment before the quiz.
(defn union
[x y]
(fn [target]
(when (or (some? (x target))
(some? (y target)))
target)))
@darclan28 Ironically, I became familiar with this style of “set” programming by taking the “Functional Programming in Scala” course at Coursera.
(defn union
[x y]
(fn [target]
(if (and (nil? (x target))
(nil? (y target)))
nil target)))
(defn union
[set1 set2]
(fn [element]
(if-some (set1 element)
element
(set2 element))))
is how i would do itIf set1
is a function (as opposed to being a clojure set), you don’t need some?
. Just call the function.
Ah, I was just re-reading the test, that’s right
The test results, that is
(if-not (nil? (set1 value)) ...
unit test is tricksy, my precious…
Actually, some?
is the better choice here. I keep thinking some?
iterates over a collection, but it’s really just “not nil”.
(defn union
[set1 set2]
(fn [x]
(if (some? (set1 x))
x (set2 x))))
(defn union
[set1 set2]
(fn [x]
(if-not (nil? (set1 x))
x (set2 x))))
(defn union
[set1 set2]
(fn [x]
(when (or (some? (set1 x))
(some? (set2 x)))
x)))
Check those, though, I think you just want (set2 x)
where you have x (set2 x)
wait, no I’m reading that wrong
(defn union [set1 set2]
(fn [v]
(if (nil? (set1 v))
(set2 v)
v)))
does that work?
ever since I quit drinking coffee, I swear… :face_with_rolling_eyes:
@jamesthibaudeau Yeah, that should work just fine
The trick is that each of your “fun-sets” should return nil if the target element is not in the set. So what happens if your set is a singleton set consisting of the value false
?
In that case, it should return false
if you pass it false
, meaning “The element false
IS a member of this set.”
which is confusing, because we naturally assume false
means it’s not a member.
I think all these things comes from wide repeated suggestion in internet not to use contains?
, cause it exists espesially for such cases
Is anyone able to explain this:
(defprotocol P
(foo [this a]
[this a b]))
(deftype T []
P
(foo [this a]
(println "foo a"))
P
(foo [this a b]
(println "foo a b")))
;; the-ns=> (foo (T.) 1 2)
;; foo a b
;; nil
;; the-ns=> (foo (T.) 1)
;; Execution error (AbstractMethodError) at kw-get/eval6029 (REPL:1).
;; kw_get.T.foo(Ljava/lang/Object;)Ljava/lang/Object;
why are are you extending P twice instead of doing it once?
(deftype T []
P
(foo [this a]
(println "foo a"))
(foo [this a b]
(println "foo a b")))
I think only the second of those was taking effect the way you had it written
... thanks @alexmiller
you can specify any number of methods under the protocol
I'm developing an application in which I need the user to provide mathematical formulae... I need to parse these formulae so they can be evaluated. Are there any libs doing something like that? So, I'd like to read some edn-string like:
{:vars [x y]
:result (* x 5 (Math/sin (/ y 7)))}
(it can be infix notation as well, but just being able to read this in clojure would certainly be fine as well. I could use something like eval
, but that's not very save 😛.
'parsing' it, would result in something like (fn [{:keys [x y]}] (* x 5 (Math/sin (/ y 7))))
Are there any existing 'math parsing' libraries?
seems like you have valid Clojure there - no need to "parse", just read
you could then write an "evaluator" that took a list and recursively applied the first op to the latter ops, but of course that's all eval is doing
if you want a whitelist, you could use a table
`{+ ~+ sin ~#(Math/sin %)...}
and only accept symbol inputs with substitutions in the table
(edit - Math/sin isn't first class)another way to go would be to rely on eval, but put your time into whitelisting
ok, let me try and see if I get somewhere. (Couldn't make it work now, but I might have done something wrong/weird 🙂 )
you could eval after the whitelisting, or even run the substitutions as an interpreter
something like this?
(defn calc
[form vars]
(let [ops-whitelist `{+ ~+ sin ~#(Math/sin %)}]
(walk/postwalk
(fn [calc]
(if (sequential? calc)
(if-let [f (ops-whitelist (first calc))]
(apply f (map #(get vars % %) (rest calc)))
(throw (new Exception (str "Cannot perform operation: " (first calc)))))
calc))
form)))
running
(calc `(+ "val1" 7 (sin 0.5)) {"val1" 5})
seems to work fine 😛ouch, naming, not really pretty (twice calc
)
I think the eval version is fine - the postwalk ensures the safety I think(?)
yeah... not sure how I would've done the eval thingy.
I posted a working example with eval / whitelisted symbols in the other thread (the one under you saying you wanted to avoid eval...)
oh, cool, thx, I'll have a look!
@noisesmith what d'you mean with run the substitutions as an interpreter
walk the input, look up the thing in function position, call it with the args once all are simplified
ie, duplicate eval :)
and bail if you hit anything that isn't a number literal and isn't whitelisted
https://github.com/rm-hull/infix/ check this out, if you're looking for external libs
yeah, saw that one, was about to start trying it, but having infix wasn't the main goal 😛
perhaps the most elegant thing is read the whole thing into lists of symbols/numbers, then tree walk and replace symbols / validate, then eval
the tree walk could just throw if it sees functions or vars that aren't allowed
or if you are OK with users hosing / abusing the machine (eg. it is their own machine) just eval :D
lol, well, the whole point was to avoid eval 🙂
the amusing thing, is if we map from symbol to safe math op, it looks like we have single quote strings
(def math-ops
{'+ +'
'- -'
'* *'
'/ /})
(edit: /' doesn't exist)
you are inherently writing an expression evaluator. it's ok to use eval for that, this is like what a lisp is good for. :)
(cmd)user=> (load-file "/tmp/mather.clj")
#'user/run-math
(ins)user=> (run-math "(+ 1 1)")
2
(ins)user=> (run-math "(+ (sin 1) 1)")
1.8414709848078965
(ins)user=> (run-math "(+ (System/exit 1) 1)")
Execution error (AssertionError) at user/whitelist (mather.clj:15).
Assert failed: the System/exit operation is not allowed
op
(require '[clojure.edn :as edn]
'[clojure.walk :as walk])
(def math-ops
{'+ +'
'- -'
'* *'
'/ /
'sin #(Math/sin %)})
(defn whitelist
[tree]
(if (symbol? tree)
(let [op (find math-ops tree)]
(assert op (format "the %s operation is not allowed"
tree))
(val op))
tree))
(defn run-math
[s]
(-> s
(edn/read-string)
(->> (walk/postwalk whitelist))
(eval)))
here's one that doesn't rely on eval:
(defn eval-math [env expr]
(let [oops (fn [msg x] (throw (IllegalArgumentException. (str msg x))))]
(cond
(list? expr) (apply (or (math-ops (first expr))
(oops "Function not in whitelist: " (first expr)))
(map #(eval-math env %) (rest expr)))
(symbol? expr) (or (env expr)
(oops "Undefined symbol: " expr))
(number? expr) expr
:else (oops "Illegal value: " expr))))
(eval-math '{x 1 y 2}
'(* x 5 (sin (/ y 7))))
;; => 1.4092142606110496
one advantage(?) of the eval version is that you get hash-maps and vectors as functions, it would be good to get confirmation that whitelisting symbols is enough to make using eval safe here
thx all, I have a few versions now 😛
is there a way to run a fixture before ALL tests (not the one in current namespace) after ALL tests? I need to spin up a few docker containers before the tests and shut them down afterwards, maybe I should use lein for it?
or write a clojure program that defines a middleware around clojure.test/run-tests
im trying to put the current timestamp in a uberjar name, assuming I can run arbitrary clojure code inside project.clj (not sure its possible)
{:uberjar {:omit-source true
:aot :all
:uberjar-name (str "cohmeia_api_local_"
(.format (java.text.SimpleDateFormat. "yyyy_MM_dd'_'HH_mm_ss")
(.getTime (java.util.Calendar/getInstance))) ".jar")
:source-paths ["env/prod/clj"]
:resource-paths ["env/prod/resources"]}
fails with java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.lang.String
Its possible to do this and am missing something or there is no way?In project.clj
you can escape code with ~
to have it evaluated.
so
:uberjar-name ~(str "cohmeia..." ...)
So is it to better to do :use or to :require? Is use akin to :refer all?
You can find other useful recomms here https://stuartsierra.com/2016/clojure-how-to-ns.html
Ok, @vemv will bookmark that site.
@sotrhraven if you haven't done so already, perhaps you will find grepping the clojure source for sierra useful some time 🙂