This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-16
Channels
- # announcements (2)
- # architecture (3)
- # beginners (72)
- # cider (15)
- # cljs-dev (27)
- # clojure (85)
- # clojure-berlin (3)
- # clojure-dev (4)
- # clojure-europe (7)
- # clojure-italy (7)
- # clojure-nl (6)
- # clojure-uk (17)
- # clojurescript (63)
- # clojutre (10)
- # core-async (10)
- # cursive (10)
- # datomic (34)
- # events (4)
- # fulcro (3)
- # funcool (8)
- # incanter (1)
- # jackdaw (1)
- # jobs-discuss (6)
- # joker (4)
- # kaocha (7)
- # leiningen (8)
- # nrepl (6)
- # off-topic (11)
- # reagent (8)
- # shadow-cljs (119)
- # spacemacs (11)
- # sql (11)
- # vim (30)
- # yada (2)
Hey! I couldn't understand this line that I saw in a blog post... :thinking_face:
(comp #{:root :todo-list :url-list} :type)
the blog post: https://vincent.404.taipei/clojure/building-trees-with-and-without-zippers/
it will extract the key :type
out of a map, and then check if the value matches any of the ones in the set
same as this (where m
is the map):
(let [k (:type m)]
(contains? #{:root :todo-list :url-list} k))
hummm, I see!
user=> (def m {:type :url-list})
#'user/m
user=> (let [k (:type m)]
(contains? #{:root :todo-list :url-list} k))
true
My tests on repl 😄Thanks @U3L6TFEJF!
Keywords act as functions that look themselves up in an associative thing and return nil
if they don't exist.
And sets act as functions that returns the arg if it is present in the set and nil
otherwise.
comp
is the mathematical function composition operator. Meaning (comp f g)
evaluates to a function equivalent to #(f (g %))
, assuming f and g are both of arity 1.
So in you're particular example:
:type
acts as the function (fn [x] (get x :type))
,
and #{:root :todo-list :url-list}
acts as the function (fn [x] (if (contains? #{:root :todo-list :url-list} x) x nil))
And the composition is equivalent to:
(fn [x] (if (contains? #{:root :todo-list :url-list} (get x :type)) (get x :type) nil))
This means keywords can be used as predicates to check whether they're present in an associative thing and are associated with a truthy value (not false and nil)
And sets can be used as predicates to check if a truthy value if contained within them.
it is veerry cool! 😮
thanks a lot @U883WCP5Z!
I can do (filter #{:x :y :z} [:a :x :y :z :b])
to get back (:x :y :z)
but (filter #{:x :y nil} [:a :x nil true 1])
returns (:x)
and not (:x nil)
. To get that, you have to do (filter #(contains? #{:x :y nil} %) [:a :x nil true 1])
.
@U8FKN7Z6X anytime!
I was just thinking a little bit about it and it feels like clojure.typed on steroids
well, I guess macro function specs are used during macroexpansion, so if you aot compile, you do see those at "compile" time
spec is primarily a runtime contract system, not a type checking system like core.typed
well, I'd say no
types are about proving things ahead of time
specs are about validating things as they occur at runtime, and is predicate-based rather than type-based
and we recommend primarily using specs at test time and not using them at runtime
answering that depends how you are using specs
One could imagine trying to use specs, or perhaps a restricted subset of them that did not execute arbitrary code, to do static checks of Clojure code, but the restrictions would be limited to what people know how to statically check in other languages, and perhaps even more restrictive due to dynamic nature of Clojure code.
whether you're calling s/valid? or s/conform (don't throw) or s/assert (throws) or stest/instrument (throws)
there is a project called Spectrum that uses specs for limited compile static analysis checks
it can't completely check all specs or all cases though
That is just blue-sky imagination of what is possible given current knowledge, but I am not aware of anyone who is even thinking of trying to implement such a thing.
i’ve seen the clj-kondo work and it feels like this work could be extended in a sense for a better analysis whether or not this is lisp/clojure way of doing things is another story
I think it is definitely against the design goals of Clojure spec to restrict the power of writing specs to only those things that people know how to check them statically.
If someone goes to the trouble of recognizing a subset of specs as statically checkable, and statically checks them, that seems like an independent project from Clojure spec.
i’m not saying the Clojure spec project is responsible for it or that the team should put this as their new goal the question is merely whether or not this is possible and worth-striving for/yields any benefits
I was surprised at how much Spectrum could do with specs
it's an independent project, and out of scope for spec
I have read the README of Spectrum before, a while ago, and then forgotten of its existence until Alex mentioned it. Might be worth checking out if you are interested, and see what its capabilities are: https://github.com/arohner/spectrum
there's a good talk on it from the conj a few years ago from Alan
thank you guys found the video. 2016. crazy that they’ve been doing this work back then already
Is there any good way of having a with-redefs
fn return different values based on the number of times it’s been called? I want to test a function that should retry on failures.
I could store the number of function calls in an atom.
close over an atom and count stuff
Thanks
Would anyone have advice on solving a Heroku deployment error? I keep getting the following error:
Could not find or load main class galleria-app.main
, which is a a section of my procfile, posted in it’s entirety below.
web: java $JVM_OPTS -cp target/galleria.jar galleria-app.main -m
(based on the Heroku/clojure-getting-started walk through && repo). I tried clojure.main as it was written originally, but it was red underlined, leading me to change it based on my namespaces, which caused the red line to disappear. I tried to use gen-class/:gen-class to no avail w/ aot(?). Aside from the resources folder, target, project.clj etc, the only real app structure is src -> galleria_app -> app.clj (which has a http://galleria-app.app ns). What might I be missing/misunderstanding/doing wrong?
seeing both galleria-app.main
and -m
is weird
typically you either do aot (so that you just specify the class of your main ns) or you use clojure.main
plus the -m
argument to specify the namespace to run
of course galleriai-app.main/-main
is allowed to take -m some-ns
as args, I just find that relatively unlikely
@lorenzo.evans94 what namespace actually implements your -main function? do you use aot?
I believe that would be (galleria-app).app, and I don’t have any :aot options in my :main in the project.clj file. I put the galleria-app in the procfile to see if perhaps the main
that was being searched for was expected to be in something called clojure
.
But yes, I do have galleria_app/app.clj and app.clj has a -main function, but for some reason the deployment fails and says Could not find or load main class clojure.main
if I use clojure.main.
then you are deploying the wrong jar I bet
your jar is a zip file - it should contain your clj files, plus the contentns of other jars you need (including clojure.jar)
a good editor can open a jar as if it were a directory, but you can also look inside it the same way you would a zip file in your os (may or may not require doing a manual rename)
Oooh, this is probably the noobest thing ever but do you have to “manually” generate jars? I was under the assumption jars were mostly for when you wanted to distribute an app so people can run it on their local machine. That being said though, thanks a lot for your help & time, I have another lead now, which should keep me busy & learning for a few days.
the command line you showed was for running a jar - if the app deploy process makes the jar for you, it still needs to ensure the jar you make includes the things you need
using a jar is usually the best way to run clojure in a "real" or production environment
@lorenzo.evans94 a common error here is that leiningen makes two jars (regular, and fat jar), and you can get the error you describe by using the wrong one
Aaah, thanks for clarifying jars for me.
Update: switched java
to lein
and got it up and deployed in no time, so I’m going to stick with that for my toy web apps for now, but am also going to be more cognizant of jars.
using lein to run an app is kind of like using make to run other programs - it's a build tool that happens to be able to run your program too
for dev / testing that's totally legit, but I'd be skeptical of using it for real work
"what version of the app was running?" "hmm, whatever was in the file sysytem when lein was called I guess..."
So, basically, if I want to have/am writing a real world sized/production level app, java & co
is the way to go to avoid headaches further down the road. Gotcha!
yeah - that way you can have a specific known artifact, lower startup overhead, etc.
I think the best rule of thumb is "if this app was written in c, would I be using a Makefile, or running the executable directly?"
if you have galleria_app/app.clj and app.clj has a function called -main
, then clojure.main -m
is correct