Fork me on GitHub

Opinions on this


Is printing a list like (1 2 3) instead of '(1 2 3) a mistake in design in clojure? often I want to paste some printed value to test something in the REPL, but I have to change these to make it work


the REPL tries to evaluate the first element of a list so when you give it (1 2 3) it will look up 1 and attempt to evaluate it with args 2 and 3... that is why you give it (quote (1 2 3)) or shorthand '(1 2 3) as in 'treat this as a list and don't evaluate the first element of teh form'. when it prints there is no need for that. difficult to articulate sorry ... or i may be absolutely wrong 😓


I know how it works, it’s just not so convenient


@borkdude it reads correctly as edn though.


hmm 🙂

(def x)
(some? x)

Alex Miller (Clojure team)12:04:35

x is unbound (unbound != nil)


how do I make a type support the seq function such that it can be used in map/reduce etc? I think the idea is to use extend-type but I'm tripped up by needing to provide an interface

Alex Miller (Clojure team)13:04:36

definitely - the interface here is clojure.lang.ISeq

Alex Miller (Clojure team)13:04:02

the core Clojure collection/seq interfaces are all Java interfaces internally

Alex Miller (Clojure team)13:04:16

I have a lot more about this in Ch 2 of Clojure Applied


so lets say I'm interop working with a 3DPoint that supports .x .y and .z and I want to be able to map over those three values. (extend-type 3DPoint clojure.lang.ISeq (seq [point] [(.x point) (.y point) (.z point)]))


something like that?


let me give er a shot..

Alex Miller (Clojure team)13:04:34

well, you’re returning a vector, which is not an ISeq

Alex Miller (Clojure team)13:04:44

so wrap (seq …) around that

Alex Miller (Clojure team)13:04:21

ISeq doesn’t have a seq method

Alex Miller (Clojure team)13:04:47

what might be more useful for you here is to implement clojure.lang.Seqable instead

Alex Miller (Clojure team)13:04:52

(extend-type 3DPoint clojure.lang.Seqable (seq [point] (seq [(.x point) (.y point) (.z point)])))


hahaha, okay, now I gotcha


ahh, I see. right right.

Alex Miller (Clojure team)13:04:18

that is, make 3DPoint something capable of returning a seq

Alex Miller (Clojure team)13:04:46

all of the core sequence functions will coerce their arg to a seq when invoked and know how to do so for Seqables



(extend-type UnityEngine.Vector2 clojure.lang.Seqable (seq [point] (seq [(.x point) (.y point)])))
System.ArgumentException: clojure.lang.Seqable is not a protocol
  at clojure/core$extend__9637.invokeStatic (System.Object , ISeq ) [0x00000] in <filename unknown>:0 
  at clojure/core$extend__9637.doInvoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.invoke (System.Object arg1, System.Object arg2, System.Object arg3) [0x00000] in <filename unknown>:0 
  at game/core$eval__38124__38136.invokeStatic () [0x00000] in <filename unknown>:0 =>   at game/core$eval__38124__38136.invoke () [0x00000] in <filename unknown>:0 
This might be an artifact of the fact that I'm working with ClojureCLR


Hi, is macro for transducer implementation of ->> good idea ( ~>>)?


Or may be there is some already?


@alexmiller Yeah I know. I was testing if a var had some value, but I should have used (which I discovered only now!)

Alex Miller (Clojure team)13:04:22

@idiomancy ah right, because this is an interface it really needs to be embedded in the type you can’t extend independently. sorry wasn’t thinking clearly. Depending on your end goals, there are other possibilities via CollReduce protocol

Alex Miller (Clojure team)13:04:23

@nicola you can do what you are asking with comp if I understand your question

Alex Miller (Clojure team)13:04:22

(comp (filter even?) (map inc)) is a transducer composition


yes but to migrate old code to transducers it would be handy just do s/->>/~>>/g


Old habits die hard.


but to move to a transducer you need a transducing context, and that's going to depend on what's going on in ->> and maybe on what's consuming it

Alex Miller (Clojure team)13:04:48

(->> foo
  (filter even?)
  (map inc)
  (partition 2))
(into [] (comp
  (filter even?)
  (map inc)
  (partition 2)


the translation tends to be very easy, but it's not something a regex can do

Alex Miller (Clojure team)13:04:27

you’ll notice some similarities there

Alex Miller (Clojure team)13:04:03

and you could just dogmatically replace one with the other, but I think you’d be doing a disservice to the options transducers open up

Alex Miller (Clojure team)13:04:22

and transducers are not always better than sequences

Alex Miller (Clojure team)13:04:39

there are tradeoffs about when to use one vs the other

Alex Miller (Clojure team)13:04:43

so I guess back to the original question, I think you should not want the thing you’re asking for :)


@alexmiller any idea where I could read up more on strategies like that? RE: collreduce

Alex Miller (Clojure team)14:04:04

if your goal is to apply a transformation (anything transducer like) to a collection, then supporting reduce is sufficient to do anything transducers can do

Alex Miller (Clojure team)14:04:31

The base interface for reduction is IReduceInit (and it’s slightly expanded child IReduce). If you control a type, I would recommend implementing one of these. But there is a protocol path into this interface as well called CollReduce and that’s good for types you don’t control as protocols can be extended to any type.

Alex Miller (Clojure team)14:04:13

so you could extend like:

Alex Miller (Clojure team)14:04:42

(extend-type 3DPoint CollReduce (coll-reduce [point f val] (reduce f val [(.x point) (.y point) (.z point)])))


hmm, seems like were almost there. throwing some kind of complaint about wrong number of args passed to core/eval but this is really good intell, I'll be playing around with this!

Alex Miller (Clojure team)14:04:21

I only implemented one of the coll-reduce fns there ^^ should probably do the other arity too

Alex Miller (Clojure team)14:04:16

(extend-type 3DPoint 
  (coll-reduce [point f] (reduce f [(.x point) (.y point) (.z point)]))
  (coll-reduce [point f val] (reduce f val [(.x point) (.y point) (.z point)])))


Will "dynamic" keywords that are created by (keyword "aoeu") be garbage collected?

Alex Miller (Clojure team)15:04:32

but no guarantee on when (you are at the whims of the GC)

Alex Miller (Clojure team)15:04:13

it is certainly possible to create a large number of them that stick around until there is memory pressure

Alex Miller (Clojure team)15:04:34

and in extreme cases, blow your heap (if you are created them faster than the GC can notice and remove them)


So it sounds like any other object or string, doesn't it?

Alex Miller (Clojure team)15:04:31

it’s different in that keywords are cached/interned

Alex Miller (Clojure team)15:04:18

which can be GC’ed but are not the first thing GC’ed

Alex Miller (Clojure team)15:04:38

and then there is a reference queue that is used to notice this cleaning, which can lag

Alex Miller (Clojure team)15:04:48

there’s an additional level now too in that keywords are made of strings and Java 8 (with a flag) and 9+ (by default) de-duplicate strings in the GC automatically

Alex Miller (Clojure team)15:04:23

so for example, if you are creating namespaced keywords, you might have many keywords that share the same namespace string and all of those strings will actually only be stored once in memory by the GC. I did some tests when this first came out, and it definitely has a (positive) effect around keywords.


Thanks. I'll have to do some profiling then.


@alexmiller I don't think string de-dup is on by default in 9+


CompactStrings is on, but that's separate

Alex Miller (Clojure team)15:04:50

[~]$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep StringDedup
    uintx StringDeduplicationAgeThreshold          = 3                                        {product} {default}
     bool StringDeduplicationRehashALot            = false                                 {diagnostic} {default}
     bool StringDeduplicationResizeALot            = false                                 {diagnostic} {default}
     bool UseStringDeduplication                   = false                                    {product} {default}
java version "9.0.1"

Alex Miller (Clojure team)15:04:18

so you’d need to set UseStringDeduplication

Alex Miller (Clojure team)15:04:47

try it out, might be useful


Is there a reason why the clojure cli tools should not run on windows? the clojure-tools is a jar file that should run anywhere I guess and the clj and clojure files are linux executables presumably?

Alex Miller (Clojure team)18:04:26

I’ve done a lot of work on this, just haven’t had time to finish it off


Thats great, like I said already, if you need someone to test, I am here.


that's being worked on, as a powershell script IIRC


@ghadi thanks, that would be great


if you have knowledge on git+ssh and git+https configuration in windows (Specifically how ssh-agent and git-credential-cache) I'm sure #tools-deps would appreciate you hanging around simple_smile


that is where the dragons lie @sveri


@ghadi My knowledge in these things is close to non existent except using it a bit. But I'd be willing to test drive everything windows related.


Since I'm on Windows 10, I do all of that sort of dev work in Ubuntu via WSL. clj etc works great there 🙂


@U04V70XH6 You also use cursive / intellij idea if I remember correctly. Does that mean you access the files on ubuntu via /mnt/c/Users/... and with intellij via the windows folder structure like c:\Users\.... Does that work seemlessly?


I use Atom/ProtoREPL, so my source is all on C: and therefore in Ubuntu it's /mnt/c/...


So editing and using the REPL is on Windows. Any command-line stuff is purely Ubuntu tho'.


Good to know, thank you.


windows in general is a big pain in the ass, not the least for lein.bat


Is there a way to write high performance code in C, Java, Kotlin, Rust, ... where: 1. we can call it from Clojure 2. the same code also compiles to webassembly, and we can call it from CLJS


1. is easy...


With a bit of glue code (writing some interfaces and annotations) JNR-FFI makes it really easy to java-ize shared libraries.


2 could maybe be relativity easy. You can easily call clojure from kotlin, and kotlin can easily be turned to webassembly. Just don't know if this approach will work, and what it does for performance.