This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-17
Channels
- # beginners (47)
- # boot (1)
- # calva (18)
- # cider (16)
- # cljs-dev (6)
- # cljsrn (14)
- # clojure (46)
- # clojure-dev (6)
- # clojure-italy (3)
- # clojure-sweden (2)
- # clojure-uk (1)
- # clojurescript (21)
- # css (1)
- # data-science (1)
- # emacs (2)
- # figwheel-main (2)
- # graalvm (11)
- # leiningen (3)
- # nrepl (19)
- # off-topic (1)
- # pathom (4)
- # re-frame (17)
- # reagent (4)
- # shadow-cljs (49)
what approach do people use for having the catch
of an exception cause early termination?
Not sure if this is what you’re looking for, but this technique is so cool that I want to mention it here: using dynamic binding to define continuations. Have a look at this video: https://invidio.us/watch?v=zp0OEDcAro0. Around 20" into the video the real magic starts 🙂
How do you handle succession of I/O logic I/O logic I/O logic .... ? Logic is pure and the boundaries between I/O logic is made with data but can the code that "orchestrate" the I/O logic flow be made pure ?
in my experience trying to make a "pure" view of an impure lower layer is a massive source of complexity and bugs, it's rarely the right thing
special cases for things like atom
- a massive engineering effort and a very carefully designed semantics to make mutation nearly pure
@johan is it possible to push all the I/O to the perimeter in your case? i.e., load everything you need up front, then logic -> logic -> logic, then finally 'commit' at the end?
Then rather than each stage of logic resulting in I/O, it would result in a plan for I/O to be conducted later
This is often talked about as "functional core / imperative shell"
e.g., https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell
@johan178 I found using a Monadic lib like https://github.com/adambard/failjure is quite useful here. Specially the ok->>
, try-all
and attempt-all
functions the lib provides
@toby924 I have been reading about "functional core / imperative shell" and what I don't understand is what goes into the imperative shell. Let's say I'm scrapping some data -> parsing -> more scrapping -> parsing -> validating -> save to db The functional core is all my parsing and validation logic, so everything else is part of the imperative shell ?
Yeah effectively
Push all the pieces that need I/O to the perimeter / boundary of the system
That's the imperative shell
Another way of looking at it is in terms of the hexagonal architecture / ports and adapters: https://dzone.com/articles/hexagonal-architecture-what-is-it-and-how-does-it
That talks about microservices but the principle is the same for other systems too
Thanks, I think my mental model of this kind of architecture is wrong, I struggle with the idea that during the lifespan of a "computation" the program will go back and forth from the functional core to the imperative shell
The goal is for it not to
@johan178 in your case, to achieve separation, you could have one subsystem do the scraping and then put that on a queue or a core.async channel that the parser can read, and the parser subsystem then puts its output on another queue/channel to another subsystem that saves to the db
now everything is separated and you are not going back and forth between “I/O <-> Not I/O” in the same place
I was listening to this episode of functional design in clojure https://clojuredesign.club/episode/024-you-are-here-but-why/ They propose to use two multi-method to handle the I/O and the logic, it sounds like what you are suggesting but without the Async part.
how come (binding [*out* nil] (.println System/out "oooo"))
throws an NPE (in my Cider REPL at least)? *out*
is not the same as System/out
, is it?
that's surely a cider bug... how would a dynamic binding shadow a jvm level object?
even in a non-cider nrepl client it prints and returns nil as expected
Cider has code to capture System/out, I'm guessing it uses *out*
to do that. So system/out is probably rebound somehow
this must be an attempt to address the ancient complaint that loggers / java code that uses System/out would go to a hidden buffer
I wasted so much time on that behavior when I was an emacs/cider user
Thanks for the responses, it was surprising to say the least 🙂
it doesn’t NPE for me:
user=> (binding [*out* nil] (.println System/out "oooo"))
oooo
nil
here’s where *out*
is defined btw: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L183-L184
How do I construct a java.lang.reflect.Type
for a generic type in Clojure? Java example gives the following: new TypeToken<Watch.Response<V1Namespace>>(){}.getType()
(where TypeToken
is com.google.gson.reflect.TypeToken
.
Java interop question, how do I call a method that has a signature like foo(A arg, B... args)
like in [AsynchronousFileChannel.open](https://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousFileChannel.html#open(java.nio.file.Path,%20java.nio.file.OpenOption...))
You have to create an array of B
s
Something like (.foo a (into-array B bs))
(into-array B [])
also works
Using sudo works as @U0CMVHBL2 suggests (thanks!)
I didn't think it was working previously as the Clojure program was not closing.. after a little investigation it seems shutdown-agents
can be used to remedy this.
(defn -main
"Entrypoint for "
[]
(println "before sudo")
(println (sh "sudo" "ls"))
(println "after sudo")
(shutdown-agents))
Yes, there is a 60-second pause after a Clojure program is finished, before it actually exits, if you use any Clojure feature that creates a future, including clojure.java.shell/sh - this is one of many things mentioned on the http://ClojureDocs.org page for clojure.java.shell/sh: http://clojuredocs.org/clojure.java.shell/sh (it mentions looking at the page for future, because all Clojure features that call future
have this property)
Thanks @U0CMVHBL2 this is very helpful