Fork me on GitHub
#clojure
<
2019-08-26
>
potetm01:08:09

The appeal of keyword arguments.

theeternalpulse04:08:56

How do you deal with cond expressions where one expression is too long so you have to break the line. Do you put the result for the predicate on a line below, and the other expressions on one line, or do you make it consistent.

theeternalpulse04:08:33

my example

(defn m-tree [leaves concat-fn initial]
  (loop [[l r & rest :as nodes] leaves
         result initial]
    (cond
      (and (empty? nodes)
           (< (count result) 2)) result 
      (empty? nodes) (recur result [])
      (and
        (and l (not r))
        (seq result)) (recur (conj result l) [])
      (and l (not r)) nodes
      (and l r) (recur rest (conj result (concat-fn l r))))))

seancorfield04:08:35

(cond (pred-1)
      (expr-1)
      (pred-2)
      (multi-line expr
                  more stuff))

seancorfield04:08:20

I find cond very hard to read when the expressions follow predicates on the same line, unless they are all vertically aligned.

seancorfield04:08:19

(so I find your cond hard to read and would complain about it in a Pull Request review 🙂 )

theeternalpulse04:08:32

(cond (and (empty? nodes)
               (< (count result) 2))
          result 
          (empty? nodes)
          (recur result [])
          (and
            (and l (not r))
            (seq result))
          (recur (conj result l) [])
          (and l (not r))
          nodes
          (and l r)
          (recur rest (conj result (concat-fn l r))))

seancorfield04:08:06

Well, apart from not being aligned under the first arg (and (empty? nodes) ,,,)

theeternalpulse04:08:23

I found this a bit harder to read, only because you can't just pop in any part and quickly know if it's an expression or a predicate

theeternalpulse04:08:30

but yea, it does align consistently

seancorfield04:08:33

In a long cond I often insert blank lines between the pred/expr pairs.

theeternalpulse04:08:54

ok, yeah that's what I naturally want to do

seancorfield04:08:38

(cond (and (empty? nodes)
           (< (count result) 2))
      result 
      
      (empty? nodes)
      (recur result [])
      
      (and
       (and l (not r))
       (seq result))
      (recur (conj result l) [])
      
      (and l (not r))
      nodes
      
      (and l r)
      (recur rest (conj result (concat-fn l r))))

Lone Ranger16:08:30

you can also consider doing core.match when your stuff starts getting crazy

Lone Ranger16:08:57

I personally like the "what you see is what you get" data approach whenever possible... FWIW, etc, etc...

chancerussell16:08:24

Anyone have advice for resolving functions from symbols in edn?

chancerussell16:08:14

For example, datomic’s ion-config.edn lets you provide fully qualified function names as symbols

chancerussell16:08:30

and at runtime, your ns is required and those functions are hooked up

chancerussell16:08:28

I can think of several ways to do it, some really stupid

chancerussell16:08:36

I guess ns-resolve is probably the move?

chancerussell16:08:34

lol, there we go

Alex Miller (Clojure team)16:08:44

which is what Datomic does

chancerussell16:08:55

Clearly I need to start skimming clojure.core after every release

Alex Miller (Clojure team)16:08:02

we've been working towards making vars rehydratable references too (Java serialization support is there now) and that's another future option for this

Alex Miller (Clojure team)16:08:50

right now, many people run into this and then need selectively resolve symbols in their data. edn vars (tagged literal representation prob) would be a way to have that happen automatically on read

seancorfield17:08:43

We were very happy to see requiring-resolve added -- it's been very useful for us!

borkdude18:08:52

is it possible to attach an error handler on a lazy collection so it will be executed when something goes bad when realizing an element?

borkdude18:08:59

I guess you can do that with lazy-seq but then you would have to wrap each element

noisesmith18:08:36

I should have figured this wouldn't work

(ins)user=> (defn lazy-basket [coll] (lazy-seq (when-let [c (seq coll)] (cons (try (first c) (catch Exception e :oops)) (lazy-basket (rest c))))))
#'user/lazy-basket
(cmd)user=> (lazy-basket (map / (rest (range 11)) (range 10)))
Error printing return value (ArithmeticException) at clojure.lang.Numbers/divide (Numbers.java:188).
Divide by zero

Graham Seyffert20:08:42

hey folks, I have a question about AOT compilation and require and how they interact with each other. My question, specifically, is - if I AOT compile my Clojure code as part of a mixed language Java/Clojure project, but then require a Clojure namespace from Java (e.g. Clojure.var("clojure.core", "require").invoke(Clojure.var("clojure.core", "symbol").invoke("a.namespace"));), will that require call re-compile that namespace, or will it use the AOT compiled class(es)?

andy.fingerhut21:08:40

require prefers a .class file when there are no .clj nor .cljc resources with corresponding names, or when both suffixes exist but the time stamps of the .class files are more recent than the source files.

andy.fingerhut21:08:49

If anything you ever try to require, either directly, or indirectly via one of the things you require also doing its own require recursively, etc., does not find a .class file, or only finds a .class file with a time stamp earlier than the corresponding source file, then the source file will be compiled.

Graham Seyffert21:08:34

Thanks, that’s pretty helpful. What kinds of actions would cause the timestamp of a .class file to change? On the surface I would only expect compilation to modify those timestamps?

andy.fingerhut21:08:48

I believe the main action that causes a .class file to be written in Clojure is compile, which can occur as part of evaluating a require expression.

andy.fingerhut21:08:03

If you are creating a JAR file with a mix of Clojure source files and .class files (whether those .class files are produced by Java compilation or Clojure compilation), then you can look at the timestamps of all of the files inside the JAR file, to see what they are. There might even be an existing tool that would warn if .class files exist with the same name as a source file, but older modification times, but I am not aware of one.

Graham Seyffert18:08:18

> f you are creating a JAR file with a mix of Clojure source files and .class files (whether those .class files are produced by Java compilation or Clojure compilation) I am, and I think it’s possible this has bitten me once or twice

nori21:08:32

@seancorfield if you encountered an error 'Caused by:ClassNotFoundException overtone.core' what steps would you take to help the compiler find the class?

nori21:08:16

fwiw in response to (ns user (:require [overtone.core :refer :all]))

seancorfield21:08:07

Sounds like you don't have the correct dependency in your project

nori21:08:56

YES cool thanks! That led me to realize that deps.edn relies on clj deps to find dependencies. I had been using lein but I'd abandoned the project.clj for a deps.edn

nori21:08:10

I'm unsure of what to make of "Exception in thread "main" java.io.FileNotFoundException: deps (The system cannot find the file specified)"

nori21:08:47

Is there some error in my deps.edn?

seancorfield22:08:39

What command gives you that error?

seancorfield22:08:01

Sounds like clj deps (which is not a thing, unlike lein deps).

seancorfield22:08:46

@norilinoriginal

(! 642)-> clj deps
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
deps (No such file or directory)
Like that?

seancorfield22:08:08

clojure/`clj` does not need a deps command (nor does lein to be honest -- it is a legacy command that used to be needed in the early days, before Leiningen changed to track stale dependencies and automatically re-check them for you).

mjw22:08:25

That’s interesting. I’ve been using lein deps when changing versions because I thought it was still necessary.

seancorfield23:08:20

@UGTAV6LR2 It hasn't been necessary for quite a while but a lot of tutorials etc never got updated. At one point Phil said "If you find you need lein deps for anything, it's a bug and I'll fix it!" 🙂

👍 4
mjw23:08:19

Good to know!

seancorfield22:08:00

If you want to see what dependencies get pulled in: clj -Stree and if you feel like you need to override/refresh the dependency cache: clj -Sforce

nori22:08:26

Yeah, clj deps is what caused it. I'll put both of those on my cheat sheet. If clj deps isn't required, though, that means that not using that wasn't the root problem of the absent dependency.

seancorfield23:08:29

clj deps means "run the script called deps" -- which is not what you intended @norilinoriginal 🙂

ahungry23:08:32

I want to make a dev tool that wraps every function in a list of namespaces with some AOP style/defadvice around like functionality that records every input and output received and produced into a database. The idea would then be editors could query the db by symbol and add static typing like i/o signatures (and even replay old i/o - benefit of unit tests and spec without any dev overhead). Is there anything like this out there atm?

noisesmith23:08:03

the only thing I know of that comes close, robert.hooke, is disrecommended by the author

noisesmith23:08:45

that said, for one off local dev stuff, you can just iterate on the values referenced by the ns - these are available via public methods and easy to use

noisesmith23:08:31

user=> (->> (all-ns) (mapcat ns-publics) (rand-nth) key)
bigint

noisesmith23:08:00

the corresponding val is the var attached to that symbol in its ns