Fork me on GitHub
#clojure
<
2020-04-19
>
dpsutton00:04:30

What's a good term for tooling to offer which program to run "a Clojure". ie, lumo, clojure, planck, bb, joker, etc. are these clojures, Clojures, or just a generic "choose a program"?

dominicm17:04:46

> ClojureScript is a compiler for Clojure that targets JavaScript. So, a clojure compiler

dominicm18:04:59

https://clojure.org/about/clojureclr lists this and clojurescript under "host"

didibus05:04:14

Oui, "host" seems good as well

didibus05:04:10

Host is probably better, I'd go with that personally

đź‘Ť 4
seancorfield00:04:05

Clojure CLIs? Clojure REPLs?

dpsutton00:04:33

just working on some wording

lilactown01:04:08

clojure runtimes?

dpsutton01:04:16

I wonder if Clojure can be genericized like that. Is there only one Clojure or can many things be a clojure?

hindol01:04:37

Clojure "flavours", maybe?

hindol01:04:48

Target or runtime?

seancorfield04:04:40

I don't think "a Clojure" makes sense. Clojure is a language so that's kind of generic by definition.

seancorfield04:04:00

It's not like "a Lisp"

salam04:04:42

clojure (proper) is based on jvm; lumo is based on node.js; plank is based on javascriptcore; babashka is based on graal; joker is, let's say, based on go. so i guess "clojure runtime environment" might be a better choice.

4
datran04:04:11

I'm running into some problems with using multimethods in a repl-driven environment. Do they not get reevaluated like regular defs?

datran04:04:46

I just spent a bit being very confused why some logging wasn't showing up. Bouncing the repl fixed things but I don't want to do that more than once a week : )

salam05:04:11

@datran if by "they", you're referring to defmulti s, then the answer is yes (quoting "Clojure Programming", p. 415): > defmulti has defonce semantics, so dispatch functions are not updated simply by reloading a modified defmulti form. The workaround is to ns-unmap the multimethod's var--which unfortunately requires reloading each of the multimethod's method implementations as well.

datran05:04:40

thanks for that! I was going a bit crazy. That's pretty unfortunate, though. I'll have to see if I can incorporate that unmapping in my workflow : /

salam05:04:01

https://github.com/clojure/tools.namespace solves that and all other sorts of problems that arise with the "reloaded workflow". if you're practicing the "reloaded workflow", you should really be using this library one way or another. 🙂

đź‘Ť 4
datran05:04:04

I am currently using juxt's clip library to handle that, which I thought used tools.namespace internally. I'll have to dig into it now

datran05:04:25

ok, clip does use clojure.tools.namespace.repl/refresh, but it doesn't look like that will unmap multimethod Vars

salam06:04:04

i just created a minimal example to verify that clojure.tools.namespace.repl/refresh correctly reloads multimethods.

salam06:04:26

i created a file: fruits.clj as follows:

(ns fruits)


(defmulti fruit :t)

(defmethod fruit "apple"
  [x]
  (println "got" x))

(defmethod fruit "banana"
  [x]
  (println "got" x))
and then, in the same directory, started a REPL as such:
clj -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.0.0"}} :paths ["."]}'
and here are the steps to verify the behavior:
Clojure 1.10.1
user=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
user=> (require '[fruits :refer [fruit]])
nil
user=> (fruit {:type "apple"})
got {:type apple}
nil
user=> (fruit {:type "banana"})
got {:type banana}
nil

;; STOP
;; Here, I switched to another
;; terminal tab where I have
;; `fruits.clj` open in vim and
;; changed the dispatch function for
;; `fruit` from `:type` to `:t`.

user=> (refresh)
:reloading (fruits)
:ok
user=> (fruit {:type "apple"})
Execution error (IllegalArgumentException) at user/eval1696 (REPL:1).
No method in multimethod 'fruit' for dispatch value: null
user=> (fruit {:type "banana"})
Execution error (IllegalArgumentException) at user/eval1698 (REPL:1).
No method in multimethod 'fruit' for dispatch value: null
user=> (fruit {:t "apple"})
got {:t apple}
nil
user=> (fruit {:t "banana"})
got {:t banana}
nil
user=> ^D

salam05:04:52

i'm not familiar with clip. i use integrant and integrant-repl and haven't had problems with reloading multimethods.

datran05:04:13

It looks like c.t.n.r/clear is the nuclear option here, I might try that

datran05:04:34

hmm, that doesn't seem to work

bortexz09:04:14

I would like to use Timbre as logging library (I am not very familiar with the java ecosystem, and would like to avoid xml’s), is there any way I can control the logs from the libraries that use tools.logging or java logs using timbre too? Also, if I would write a library, would use timbre for logs cause a headache for users of the library that do not use timbre? If someone has any resource that explains/compares these 2 logging strategies would be great

bortexz09:04:11

Expanding a bit, I would like to log maps, not strings (strings would be {:description msg})

bortexz09:04:46

At first sight, it seems Timbre would be ideal for “application-level” logging, looks like using https://github.com/fzakaria/slf4j-timbre you can forward almost everything to timbre and from there control the appenders. On the other hand, looks like clojure.tools.logging would be preferred for a library, to let the user of the library decide which backend to use for logging

hindol10:04:50

I am familiar with the Java and SLF4J ecosystem. You are right, libraries should always depend on slf4j-api only and the final app that is using those libraries specify a suitable implementation which will magically receive all the logs from all the libraries. For app level logging as well, I like using slf4j-api because then I can switch the logger implementation at will. You can use Timbre directly, but be aware of the tradeoffs.

đź‘Ť 4
nick18:04:33

@UJRDALZA5 would you mind giving some Timbre tradeoff examples? That's interesting

hindol18:04:56

Sorry, I wasn't clear enough. The tradeoff is, you are tying your code to a specific implementation (Timbre) rather than a facade (interface, SLF4J). I did not mean Timbre itself has some tradeoff, well, there might be, but I am not aware.

đź‘Ť 4
Adam Helins12:04:37

What's the name of those vectors where the first item is a keyword representing an operation and the rest are arguments, like in Re-frame? I remember a talk where a specific name was given, but cannot manage to recall it.

Adam Helins12:04:50

Nope, more of a concept in functional programming, something more specific

jaihindhreddy12:04:47

event, command, mutation are all used commonly

Adam Helins12:04:52

I am fairly sure there is a more sophisticated name, I am looking after that talk but it was years ago I think

mpenet13:04:27

Named tuple maybe

mpenet13:04:50

But that's more an erlang thing than fp

Adam Helins13:04:36

Well, "vector variants" to be more precise, I guess

jsn13:04:23

So it's like DIY variant types

thheller13:04:14

how do I permanently and globally turn off clojure generating errors reports in /tmp instead of printing the errors directly?

Full report at:
/tmp/clojure-319502167327667627.edn

thheller13:04:49

I know its done in the spirit of better error messages but this is just worse for me

borkdude14:04:45

@thheller I looked this up in main.clj:

--report target     Report uncaught exception to \"file\" (default), \"stderr\",
                        or \"none\", overrides System property clojure.main.report