Fork me on GitHub
#clojure
<
2019-08-17
>
dominicm10:08:41

what approach do people use for having the catch of an exception cause early termination?

Stefan11:08:21

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 🙂

Johan11:08:31

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 ?

noisesmith18:08:35

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

noisesmith18:08:12

special cases for things like atom - a massive engineering effort and a very carefully designed semantics to make mutation nearly pure

👍 4
Toby Clemson11:08:35

@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?

Toby Clemson11:08:57

Then rather than each stage of logic resulting in I/O, it would result in a plan for I/O to be conducted later

Toby Clemson11:08:45

This is often talked about as "functional core / imperative shell"

lispyclouds11:08:40

@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

👍 4
Johan12:08:32

@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 ?

Toby Clemson12:08:59

Yeah effectively

Toby Clemson12:08:13

Push all the pieces that need I/O to the perimeter / boundary of the system

Toby Clemson12:08:33

That's the imperative shell

Toby Clemson12:08:54

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

Toby Clemson12:08:16

That talks about microservices but the principle is the same for other systems too

Johan12:08:53

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

Toby Clemson12:08:37

The goal is for it not to

schmee12:08:21

@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

schmee12:08:50

now everything is separated and you are not going back and forth between “I/O <-> Not I/O” in the same place

Johan12:08:52

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.

stathissideris17:08:09

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?

noisesmith18:08:23

that's surely a cider bug... how would a dynamic binding shadow a jvm level object?

noisesmith18:08:53

even in a non-cider nrepl client it prints and returns nil as expected

dominicm18:08:48

Cider has code to capture System/out, I'm guessing it uses *out* to do that. So system/out is probably rebound somehow

noisesmith18:08:15

this must be an attempt to address the ancient complaint that loggers / java code that uses System/out would go to a hidden buffer

noisesmith18:08:48

I wasted so much time on that behavior when I was an emacs/cider user

dominicm19:08:45

That's exactly what it is

stathissideris09:08:40

Thanks for the responses, it was surprising to say the least 🙂

schmee17:08:05

it doesn’t NPE for me:

user=> (binding [*out* nil] (.println System/out "oooo"))
oooo
nil

dottedmag22:08:54

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.

pablore23:08:05

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...))

Toby Clemson23:08:32

You have to create an array of Bs

Toby Clemson00:08:20

Something like (.foo a (into-array B bs))

pablore01:08:29

and if i want to use an empty array?

pablore01:08:18

nvm, you can use (make-array B 0)

Toby Clemson09:08:07

(into-array B []) also works

mikepjb23:08:49

Does anyone know how to execute commands with sudo using clojure.java.shell?

mikepjb07:08:48

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))

andy.fingerhut07:08:18

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)

👍 4
mikepjb06:08:35

Thanks @U0CMVHBL2 this is very helpful