This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-15
Channels
- # announcements (11)
- # beginners (66)
- # boot (6)
- # clara (25)
- # cljdoc (4)
- # cljs-dev (22)
- # clojure (261)
- # clojure-dev (1)
- # clojure-europe (2)
- # clojure-italy (15)
- # clojure-losangeles (1)
- # clojure-nl (19)
- # clojure-spec (62)
- # clojure-uk (50)
- # clojurescript (12)
- # community-development (6)
- # cursive (60)
- # datomic (21)
- # emacs (2)
- # figwheel (2)
- # figwheel-main (3)
- # fulcro (2)
- # graphql (11)
- # hyperfiddle (11)
- # javascript (1)
- # jobs (6)
- # juxt (1)
- # kaocha (5)
- # keechma (2)
- # off-topic (4)
- # onyx (10)
- # pathom (7)
- # re-frame (15)
- # reagent (8)
- # remote-jobs (2)
- # ring-swagger (14)
- # shadow-cljs (35)
- # sql (22)
- # testing (9)
- # tools-deps (62)
- # vim (12)
how does one chain compose together filter fns? i’m having a brain fart and can’t figure out what’s wrong here:
filters (comp
(filter #(contains? % :person/foo))
(filter #(contains? % :person/bar))
)
{keep true
drop false} (group-by filters d)
what i really want is a composed filter chain and to use group-by to keep the values filtered as well as the values not filtered
so more like (group-by #(or (contains? % :person/foo) (contains? % :person/bar)) d)
yea that’s probably a more straightforward way. i thought i could get fancier, but i see that what i’m trying to do doesn’t really make sense and might need to be wrapped in a transducer
I don't think group-by
accepts a transducer like you're calling it. If you must use a transducer you use it in a way such that what is being passed to group-by is a function. For example, the following code uses a transducer to filter elements and place the remaining ones into a set. The set is then used as the function to determine if a value from the collection exists in the output of the transformation of the transducer.
(def coll
[{:a 1 :b 2 :c 3}
{:a 1 :b 2}
{:c 1}
{:b 3}
{:a 1}])
(def xf (comp (filter #(contains? % :a))
(filter #(contains? % :b))))
(group-by (partial contains? (into #{} xf coll)) coll)
or #(boolean (seq (select-keys % [:person/foo :person/bar])))
it does or rather than and though
Breaks your program and checks if the tests still pass. If they do, you need more tests.
I'd like to filter a list returning all values until a particular value is found, and stop at that point. e.g. 1, 2, 3, 4, 5, 2
should return 1, 2, 3
if 3
is the target. Thus filter
is no good. Do I need recursion or is there a more idiomatic way of achieving this?
oh yeah @lukas.rychtecky, that's perfect! Thank you.
@paulspencerwilliams you welcome, or you can play with https://clojuredocs.org/clojure.core/split-with
there’s a ticket for adding take-until, you can copy the implementation from the patch and use that: https://dev.clojure.org/jira/browse/CLJ-1451
Yeah, I've just picked that fact up. I'm currently playing with split-with
and joining the first sequence, and head of the second sequence (i.e. the target item).
That patch function is much better however.
That's perfect, thank you both! take-until
was exactly what I wanted.
I'm having a very mysterious (for me) behaviour, the same exact code works perfectly fine in development, but when I try to do a lein run
I get something like
Exception in thread "main" clojure.lang.ArityException: Wrong number of args (0) passed to: middleware/wrap-exceptions/fn--42042, compiling:(/private/var/folders/c2/47k4xqq92gld005q_8df532nh8hy8l/T/form-init3592174147248454589.clj:1:125)
this comes from the actual app-handler which is something like
(def app-handler
(-> routes
(make-handler spa-handler)
(mw/wrap-exceptions ex/notify!)
....
but it's not a problem with the actual functions at all, they all fail for the same reason one after the other in inverse order, all complaining that I'm passing 0 arguments, while it's always 1 or even 2
I guess it's some kind of weird aot compilation issue maybe, anyone ever had this problem?
mm never mind I found out, it was just because I was calling (app-handler)
which now is a def, so the error was rather confusing but I guess it makes sense
Please don't ask me why (answer: I'm an idiot) I need something that is equiv to "uber grep" -- it needs to look through all files in ~/ , all .zip, all .tgz ... and it needs to find me blocks of code that are clojure code. There's no guarantee that the file ends in .clj or .cljs (basically, I have a 4000 line of clojure code stored as a COMMENT in either a .kt kotlin or .rs rust file ... and I think it's in some .zip or .tar or .tgz or .tar.gz -- and I need to find this block of code).
write a script that counts the number of parenthesis in each file and then sort it by count
that's brilliant, 4k lines f clojure ==> at avg of 3 ()/line, that's 12000 () pairs in the file, something most files ar eunlikely to have
(ns test.core
(:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(.addShutdownHook (java.lang.Runtime/getRuntime)
(Thread. (fn []
(println "Shutting down")
(shutdown-agents)
(prn 2))))
(future (fn []
(do (println 1)
(Thread/sleep 1000)
(println 3))))
(System/exit 0))
can someone tell me why this code never prints 3? i tried running it every way i can think of. lein trampoline run
, lein run
, lein uberjar
and running with java -jar
, removing (System/exit 0)
and quitting with Ctrl+C
.In my my understanding of the JVM, when (System/exit 0) is run, it executes all of the hooks, then kills all the threads.
https://clojuredocs.org/clojure.core/shutdown-agents hmm -- How is "future" related to agents ?
@marcus165: In your opinion, should the "3" also be printed, for the reasons @apa512 stated?
@apa512 looking at the source for shutdown-agent, it calls shutdown
on the thread pools
in the docs for shutdown, it says: > This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
strange though cause the docstring for shutdown-agents says something else… https://clojuredocs.org/clojure.core/shutdown-agents
try removing the (fn [] ...)
in the future
call, future wraps up the body in a fn by itself
your code create a future the creates a function and then exits, it never actually calls the function
yes, i was trying a lot of different things. but still the same behavior if i call the future correctly.
hello guys! by convention, when a function name ends with *
what that means?
By convention, it is similar to prime
in mathematics. I usually see it used as the implementation/helper.
Ex.
(defn my-fn* [a b]
…
)
(defn my-fn [a b]
…
(my-fn* [a b]))
it can be useful in macros too to avoid name-clashing. See https://clojure.github.io/test.check/clojure.test.check.properties.html for instance
tks, @nha! I'll read more about it.. for now, i'm pretty sure that I should have give more thought to the math classes.. 'cause I couldn't understand what you mean by "... similar to prime in maths" 😕
(shutdown-agents)
(.awaitTermination clojure.lang.Agent/soloExecutor
10
java.util.concurrent.TimeUnit/SECONDS)
for anyone who's interested in the shutdown-agents
problem, ^ seems to do the jobArityException Wrong number of args (-1) passed to: core/ptype clojure.lang.Compiler.macroexpand1 (Compiler.java:6917)
Wut? 😮how can number of args be -1 😅
oh right... 🙂
yeah makes sense
I was off by one in a list
when writing project.clj for a library, should I mark clojure dependency as provided?
So after some useful tips from @lukas.rychtecky and @schmee about take-until
, I wondered how people typically handle non-merged patches to Clojure in their projects? Fork, merge, and reference from deps.edn
? Include the patch in a patches ns?
it’s a function - just put it in your code?
you don’t need a patched version of clojure
the cool thing about functions is anyone can make one
if (and it is if) it gets added to Clojure later, your code will still work fine. you’ll get a warning that you’re shadowing core, which you can either ignore, or remove your version, or refer-clojure :exclude to keep using yours and not get the warning
Cheers @alexmiller, that’s what I’ve done up until now. The possible future core addition was what I was concerned about.
we’ve worked hard to make that a non-issue
Thanks to those that have enabled this, and to your fast and authoritative advice 👍
@thheller Very few libraries mark clojure as provided though
@marcin.k.chmiel I wouldn't -- I'd put the shared code in a src
file and have project.clj
pull that in, I think. I've also seen examples that use an EDN file or a text file for simple values that need to be pulled into project.clj
as well as "regular" code.
@seancorfield Thanks. The first approach is what I started doing
there's a way to get that stuff into your project. slothcfg gives your project the project.clj map with all of the merging done. we deeply regret going down this route right now
Or move to clj
/`deps.edn` and have a "pure" dependency config file with the "shared vars" in actual code 🙂
^ we are envious of this in our main web app. our libs are migrating over to deps edn and we are loving it
We just completed a full migration from Boot and we're very happy. Deleting our 2,000 line build.boot
file was a nice milestone.
migration to ?
Interesting. I don't do that much clojure to be honest, just in between of my regular job. When I started learning clojure leiningen seemed to be (more or less) the standard.
@coinedtalk to clj
/`deps.edn`.
@marcin.k.chmiel Well, Leiningen is going to remain the de facto standard for a while because it's so well-established and all the books and nearly all the online tutorials use it. But, yes, I'd recommend at least trying the new CLI tools that the Clojure team have built.
We use (a fork of) depstar
for building uberjars for deployment. We use Cognitect's test-runner
for running all our tests (including our expectations
tests).
lein has good stories around deployment and artifact creation. there's a plugin that reads deps from deps.edn files so our stuff has mostly had a thin project.clj file for deploying to private repos and creating jars
honestly the ideal to me sounds like boot tasks for artifact/deployment and deps.edn for dev
@dpsutton I'm rather liking the depstar
approach -- my fork supports both uberjars (for production app deployment) and "thin" JARs for Clojars/Central deployment. For now I'm using mvn deploy:deploy-file
for pushing to Clojars, after creating a pom.xml
with clj -Spom
(and a one-time editing pass to expand the information there).
but we also need deployment to private s3 repo and lein works so easily so it kinda won out
didn't know about the mvn deploy stuff. i'm still a newcomer to actual java/jvm land. To some people clojure is a java program and to others its a language 🙂
I'm not thrilled about having to use mvn
for Clojars deployments 🙂 There's a recent deps
-based project that does the "push" using the pomegranate library that I need to check out...
I'm experimenting agents, I have a while loop of an audio loop, which I start with this fn
let [thread (agent csnd)]
#(send-off thread
(fn [instance]
(while (zero? (perform-ksmps instance)))))
which works fine at this point, my problem is signaling "stop", which I currently try to do this way
#(send-off thread (fn [instance] (stop instance)))
but nothing happens. Should I add some checking mechanism into the while loop? Not sure what's the best way. (I could use core-async thread or (Thread. ...) but I'd like to learn some agents).@noisesmith You've said a couple of times about some libs not playing nice with jdk11. I'm working on fixing stuff like that, can you give me a list?
I just know I've seen it in forums and bug tickets, but I don't have something handy, sorry - I'll make a note to document that in the future
at one time our friend @tcrawley was collating these issues for 1.9
I think a lot of the stuff on the above link is still relevant for 11
@noisesmith howdy!
@jwhitlark I was tracking java 9 issues at https://github.com/tobias/clojure-java-9/issues, but I haven't really kept up with it
the xml.bind issue is different in 9 and 10+
yeah - I trust the very competent Clojure team to fix these things, my main concern personally is regressions in miscellaneous libs
in 9, it’s no longer in the base module and you can run into reflective access issues (those are actually a warning). in 10, they removed it entirely so you need to do something to add either the module or the lib
the main thing we ran into with 11 is the new arity in Collection.toArray() which made existing calls/impls ambiguous
those have been fixed in Clojure and in contribs that have the issue, but you might encounter it if you have your own reifications of Collection
I don’t know of any other Java 11-related issues
if you find one, please file a CLJ ticket
I’ve been using Java 11 as my default for several months now, haven’t had any problems
@alexmiller Any chance we can get a hint of direction on https://dev.clojure.org/jira/browse/CLJ-2365 It's currently high on my wishlist. I don't mind working on it or testing it, but if it's not seriously under consideration....
it’s post 1.10 so I’m not going to look at anything for it right now
we’d like to do something there
The attached patch is interesting but has some potential downsides that need to be assessed
one possible issue is whether those added function calls will conflict with other existing impls of IFn (some of which may not be in clojure itself)
I think they actually mostly do not, which is good
the bigger question is whether this would actually be enough to allow Clojure functions to act in a Java SAM context and get all of the high-performance treatment they are doing now (since our functions have a lot more “stuff” on them)
It's a pity there's not a way to do this as a library for the moment. But AFAIK, you can't extend IFn without a custom clojure build?
if the above is not true, then it would work from a Java type perspective, but may not actually give you the performance a Java user expects and that would be sad
so that’s kind of an open question, which could be investigated
So, my understanding is that as SAMs are implemented via invokedynamic, it makes it a tricky case? Where if we just implement the interface, we'll basically get the correct behavior, but will probably be slower since it's using the regular class machinery?
the desire is to make it “like Java” in performance
do we get that? if so, then cool. if not, then it might end up needing something more.
i'm seeing an NPE in
- apparently because the ContextClassLoader referenced here is nil - https://github.com/clojure/clojure/blob/ee1b606ad066ac8df2efd4a6b8d0d365c206f5bf/src/clj/clojure/java/io.clj#L450
javadocs seem to indicate that nil/null is a reasonable value for the ContextClassLoader - https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#getContextClassLoader--
so that looks like a bug in io.clj
?
okay, this is driving me crazy, can someone please help me figure out what’s going on here?
(defn print-three [a b c]
(println a b c))
(defn wrapper [f]
(fn [& args]
(apply f args)))
(defn foo [f]
`(let [a# ~f]
a#))
(do
(eval (foo print-three)) ;; this works
(eval (foo (wrapper print-three)) ;; this doesn't
))
when I print the form that’s to be evaled, in both cases they both look like functions, but the first one works and the second one gives
java-http-clj.core=> (eval (foo (wrapper print-three)))
Execution error (IllegalArgumentException) at java_http_clj.core$eval21417/<clinit> (form-init14437179902714
598852.clj:1).
No matching ctor found for class java_http_clj.core$wrapper$fn__20910
Maybe a classloader thing? Doesn't eval
create a classloader for the evaluation, so an anonymous function passed in is going to have been compiled into a class in a different classloader? :thinking_face:
If you change foo
to a macro it works.
(or, at least, it doesn't blow up)
user=> (defmacro foo [f] `(let [a# ~f] a#))
#'user/foo
user=> (eval (foo (wrapper print-three)))
#object[user$wrapper$fn__146 0x2f48b3d2 "user$wrapper$fn__146@2f48b3d2"]
user=> (eval (foo (wrapper print-three)))
#object[user$wrapper$fn__146 0x44e3a2b2 "user$wrapper$fn__146@44e3a2b2"]
user=> ((eval (foo (wrapper print-three))) 1 2 3)
1 2 3
nil
user=> ((eval (foo print-three)) 1 2 3)
1 2 3
nil
user=>
But maybe that won't help for your use case.for sort of arcane reasons this tends to work if the function doesn't close over any values, and explodes if it does
I see! I’m actually surprised that the first one works, but I would’ve expected both to work or both to fail
interesting meta-question… why can i call first
on anything that’s associative but not ordered/sequential?
(first my-map)
semantically doesn’t make much sense; what’s the “first” thing of a non-ordered collection?
because the item is seqable?
it is seqable? because it's useful to iterate, as a side effect of this calling first works
I would argue that if you are using eval in a macro you are mixing levels in the stages of read -> macro expand -> compile -> run in ways that you shouldn't
your code has a specific meaning at each stage, and trying to use the meaning from a later stage in an earlier stage is going to be broken
yeah the thing I’m doing is totally stupid, spent two hours with insane macro gymnastics just to avoid one function call 😂
but once you start dabbling in the dark arts (macros that mess with time or matter (state))
it’s definitely true that once you start using macros, it starts to “infect” the surrounding code and suddenly everything has to be macros
yeah, if you use values at earlier stages in the pipeline, then they must be available at earlier stages of the pipeline
@dpsutton (intern *ns* 'my-fn (fn* [x] ....))
- not that I recommend writing code that way, and arguably special forms are worse than macros
oh, and then use with-meta
to attach a doc-string, of course :D
since a reader macro would be cheating
proxy can use proxy-super
here’s what I can’t figure out:
(reify WebSocket$Listener
(onOpen [this ws]
(if on-open
(on-open ws)
(.onOpen this ws)))
I want the .onOpen
to use the default method, but since I’ve already overrided the onOpen
in my reify, it just loops and stack overflows
from a little reading, you can't invoke the default interface method from a clojure implementation of the interface
it requires an invokespecial to call it, and clojure only emits those for constructors
I think the "official" way to handle that is to use a proxy instead of reify so you can use proxy-super
(if on-open
(reify
WebSocket$Listener
(onOpen [this ws]
(on-open ws)))
(reify
WebSocket$Listener))
(defmacro websocket-listener-fast
([{:keys [on-binary on-close on-error on-open on-ping on-pong on-text]}]
`(let [~'ob ~on-binary
~'oc ~on-close
~'oe ~on-error
~'oo ~on-open
~'opi ~on-ping
~'opo ~on-pong
~'ot ~on-text]
(reify WebSocket$Listener
~@(when on-binary
[`(~'onBinary [_# ws# byte-buffer# last?#]
(~'ob ws# byte-buffer# last?#))])
~@(when on-close
[`(~'onClose [_# ws# status-code# reason#]
(~'oc ws# status-code# reason#))])
~@(when on-error
[`(~'onError [_# ws# throwable#]
(~'oe ws# throwable#))])
~@(when on-open
[`(~'onOpen [_# ws#]
(~'oo ws#))])
~@(when on-ping
[`(~'onPing [_# ws# byte-buffer#]
(~'opi ws#))])
~@(when on-pong
[`(~'onPong [_# ws# byte-buffer#]
(~'opo ws#))])
~@(when on-text
[`(~'onText [_# ws# char-seq# last?#]
(~'ot ws# char-seq# last?#))])))))
you are trying to do the conditional at macro expand time instead of at runtime, which is your problem
here’s the final product, it actually works 😂
(defn websocket-listener-fast [ks]
`(reify WebSocket$Listener
~@(when (ks :on-binary)
[`(~'onBinary [_# ws# byte-buffer# last?#]
(~'on-binary ws# byte-buffer# last?#))])
~@(when (ks :on-close)
[`(~'onClose [_# ws# status-code# reason#]
(~'on-close ws# status-code# reason#))])
~@(when (ks :on-error)
[`(~'onError [_# ws# throwable#]
(~'on-error ws# throwable#))])
~@(when (ks :on-open)
[`(~'onOpen [_# ws#]
(~'on-open ws#))])
~@(when (ks :on-ping)
[`(~'onPing [_# ws# byte-buffer#]
(~'on-ping ws#))])
~@(when (ks :on-pong)
[`(~'onPong [_# ws# byte-buffer#]
(~'on-pong ws#))])
~@(when (ks :on-text)
[`(~'onText [_# ws# char-seq# last?#]
(~'on-text ws# char-seq# last?#))])))
(def fns [:on-binary :on-close :on-error :on-open :on-ping :on-pong :on-text])
(defmacro dear-god-why [subset]
`(case ~subset
~@(mapcat
(fn [s] [(set s) (websocket-listener-fast (set s))])
(combo/subsets fns))))
(defn do-the-thing
[{:keys [on-binary on-close on-error on-open on-ping on-pong on-text] :as fns}]
(dear-god-why (-> fns keys set)))
ohh yeah if you're not actually working with a class then you likely can't use proxy. my bad, misread the situation