This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-19
Channels
- # announcements (10)
- # aws (3)
- # aws-lambda (1)
- # babashka (24)
- # beginners (57)
- # boot (5)
- # calva (20)
- # chlorine-clover (3)
- # cider (14)
- # clj-kondo (37)
- # clojars (17)
- # clojure (200)
- # clojure-dev (40)
- # clojure-europe (9)
- # clojure-france (7)
- # clojure-gamedev (5)
- # clojure-hungary (4)
- # clojure-italy (8)
- # clojure-losangeles (2)
- # clojure-nl (9)
- # clojure-uk (97)
- # clojurebridge (1)
- # clojured (3)
- # clojuredesign-podcast (23)
- # clojurescript (13)
- # code-reviews (2)
- # component (22)
- # core-typed (7)
- # cursive (64)
- # datascript (12)
- # datomic (60)
- # emacs (6)
- # fulcro (54)
- # graalvm (11)
- # graphql (3)
- # hoplon (25)
- # jobs (1)
- # joker (85)
- # juxt (5)
- # kaocha (10)
- # klipse (8)
- # malli (2)
- # off-topic (36)
- # parinfer (1)
- # pathom (1)
- # re-frame (9)
- # reagent (4)
- # reitit (1)
- # remote-jobs (1)
- # shadow-cljs (24)
- # spacemacs (1)
- # sql (39)
- # tools-deps (10)
- # tree-sitter (18)
- # xtdb (18)
You can't in Spec 1. In Spec 2, you can do that for unqualified keys but not qualified keys.
(and you are using unqualified keys -- :req-un
-- so you'll be happy with Spec 2 in that regard.
(-> {:a 20 :30}
:a)
=> 20
(-> {:a 20 :b 30}
(:a))
=> 20
I thought this was a little weird... Is there a preference? Why do they produce the same result?->
isn't a normal function, it's a macro that automatically adds parens if they are absent
I prefer to always use parens for consistency, but part of the point of ->
is to reduce character count, so
user=> (source ->)
(defmacro ->
"Threads the expr through the forms. Inserts x as the
second item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
second item in second form, etc."
{:added "1.0"}
[x & forms]
(loop [x x, forms forms]
(if forms
(let [form (first forms)
threaded (if (seq? form)
(with-meta `(~(first form) ~x ~@(next form)) (meta form))
(list form x))]
(recur threaded (next forms)))
x)))
nil
the magic happens in the (if (seq? form) ... (list form x))
so in the else, when it isn't in parens, it puts it in parens
Oh neat! So even if I don't put it in parens, it'll do it for me. I was thinking about leaving it in anyway for consistency, like you said. It just made me curious because I was surprised it was allowed
it's pretty common to see both, but it's definitely good style to pick one and stick to it, per project at least
Okay, thanks for your help!
Not sure if your above was just an example of using one of the threading macros, but in said example, you really dont need it:
({:a 20 :30} :a)
=> 20
@hindol.adhya Not quite: the parens are added wherever there aren't parens. Consider (-> 42 cons)
-- cons
is a two-arg function but the parens are added and the result is an arity exception because it becomes (cons 42)
which is invalid.
Similarly, (-> x :k)
becomes (:k x)
(which is valid)
Yes, I actually meant that. Don't know why I wrote it this way. It's technically incorrect.
Parens are added whenever they are omitted ๐
I mean every single thing without paren will be put in paren. For example, (-> [1 2 3] map square), map and square will be put in separate parens, which is wrong.
Although (map [1 2 3])
is legal (it returns a transducer) ๐
(it's not a useful transducer since [1 2 3]
is not a reducing function)
(-> [1 2 3] map square)
=> (square (map [1 2 3]))
๐
Question related to Datomic Ions, but I think the answers are much more about the basics so asking here. In Ions you pass a handler function to either Lambda or http entry points, and the rest of system management is abstracted away. In particular, I wasn't sure where we could hook into system startup (basically whatever the equivalent of -main
is), and saw that the provided ion-starter solved these initial configuration-like steps with memoize
on client but was basically hitting the database every call to check if a starter dataset was loaded.
I'm looking to use larger system management libraries like component/mount/integrant but I'm not sure where to call component/start
. What are best practices here, and what are some patterns I could use? Can I rely on the idempotency of start
in these libraries and basically call it on every request? I was thinking of just closing over an atom to return a handler that does a simple in-memory check like so:
(defn run-once [handler]
(let [started (atom false)]
(fn [& args]
(if @started
(apply handler args)
(do
(println "system start functions called here")
(reset! started true)
(apply handler args))))))
Are there better/simpler solutions with delay
or memoize
? Am I missing something really basic?Hi
I'm very new with clojurescript
I download a website template and put it in the resource directory and now after
lein trampoline run -m figwheel.main -b dev -r
I can see the template in the browser but the repl won't work anymore, however, the only change is in the resources
I also don't get any warning or exception
Do you have any idea about the possible reasons?
(The figwheel logs stop just before print clojurescript version)
silly Q but is there any way to convert KEY to INT. :1 -> 1
instead of converting to string?
Yea I want without the string convertion
@USPQF75AS It looks like itโs stored as a String based on this source below, which means probably that the idea from @ben is the best https://github.com/clojure/clojure/blob/clojure-1.9.0/src/jvm/clojure/lang/Symbol.java#L40-L42
Yea that's what I thought, k thanks
Hello. I have the following macro, which works
(defmacro make-fn [name args body]
`(fn ~name ~args ~body))
I can execute this from the repl as follows
(make-fn add [x y] (+ x y))
However, if I invoke make-fn
from a function, the spec fails while macroexpanding fn
user=> (defn fn-maker [name args body] (make-fn name args body))
Syntax error macroexpanding clojure.core/fn at (form-init14866211691412444997.clj:1:33).
args - failed: vector? at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
args - failed: (or (nil? %) (sequential? %)) at: [:fn-tail :arity-n] spec: :clojure.core.specs.alpha/params+body
And this is while defining, not while calling.
It seems like fn, understandably, enforces its args to be a vector
Just trying to understand this a bit better. So the spec is invoked at defn time?
it's validated during macroexpansion
which is actually what it says there "syntax error macroexpanding clojure.core/fn"
Right. I am curious about fn being a macro. I know the same to be true of let as well. Both are listed as special forms which expand to fn* and let*
you should probably treat that as implementation details
Ok ๐
Someone I know is using instaparse to write a language and they are writing a bunch of macros which expands their language to runnable Clojure code
you can turn off spec macro checking
(but anyone would need to do that to use this)
Ok, thanks @alexmiller.
or you could tweak that macro definition to be a vector
Oh thatโs a good idea
(defmacro make-fn [name args body]
`(fn ~name [~@args] ~@body))
something like that (the body not being a splice quote was a bug), but depends a bit on what you're trying to do
No, this works. Thanks
Is spec a correctly sized hammer for this nail? All the simulated objects in my game have their state in a map, including function identifiers, and I need my code to yell at me if a new map is missing critical keys or if the functions it identifies choke on it's data when run. I could just do a series of checks, but if this is the correct use case for spec, I'll use that so I can get an understanding of what everyone's so excited about!
seems like a possible match
Cool, I'll give it a go then