Fork me on GitHub

Is there a way to refer to an unevaluated form inside a macro without doing the following ?

(defmacro debug [form]
  `(do (println (list ~@form)) ~form))


(defmacro debug [form]
     (println ~(list 'quote form))


@U45T93RA6 Thanks. I guess you can’t do it without somehow making a list of it again.


that's not a list, in the same way that 'x is not a list (clojure implements 'x as a list though... which is why my macro looks like that)


I love how approachable the core.async src is. I mean, 90% is way over my head, but it’s like 1000x less scary than I imagined it for what it’s accomplishing.


watch tim baldridge's videos on the macros. they are well worth the time

👍 5

Is there a good writeup about #= reader conditional? I tried using it and it has very confusing semantics:

'{:a #=(vec (list [1 2 3]))}
=> {:a [list [1 2 3]]}
{:a #=(vec (list [1 2 3]))}
=> {:a [#object[clojure.lang.PersistentList$Primordial 0x488c6b35 "clojure.lang.PersistentList$Primordial@488c6b35"] [1 2 3]]}
It's like it evaluates first function but quotes the argument list of the said function

Alex Miller (Clojure team)10:02:51

It’s happening at read time so no evaluation has occurred on the args

Alex Miller (Clojure team)10:02:15

It’s intentionally not doc’ed because it’s not a public feature


I often need to assoc a key to a map if it does not already exist. This is how I usually do it (if (:foo m) m (assoc m :foo (compute-foo))). Is there a nicer way to do this?


(assoc m :foo (or (m :foo) (compute-foo)))


But this would invoke (compute-foo) even if :foo is already set. 😞


I had or in my first response, then changed it to a map-get operation, then back to or because of this. or is lazy.


or is lazy? Thanks!


user=> (doc or)
([] [x] [x & next])
  Evaluates exprs one at a time, from left to right. If a form
  returns a logical true value, or returns that value and doesn't
  evaluate any of the other expressions, otherwise it returns the
  value of the last expression. (or) returns nil.

Noah Bogart15:02:16

I have a vec of symbols and quoted function calls to be used in a let-binding macro that I've quoted, and I want to turn it into a map so I can use the symbol as the key and get the quoted function back. I currently have the vec quoted, and in a thread macro I call (partition 2) (map (juxt first identity)) (into {}) which neatly handles what I'm looking to do. My question is, why do I need to call (map (juxt first identity))?

Noah Bogart15:02:32

If I leave it out, I get the clojure.lang.Symbol cannot be cast to java.base/java.util.Map$Entry error, but if I put it in, I've just created a list of ['symbol '(symbol (function call))], right?

Noah Bogart15:02:49

What am I missing in this situation?


(into {}) expects a sequence of 2-vectors, [key val], that will become key-val pairs in your map. So, (map (juxt first identity)) puts them in that form.

Noah Bogart16:02:59

Ah, okay. Thanks


I used float-array to pass a Java array of float to a Java method. That method returns me back an array of float. Is there a sister function of float-array that does the inverse, so that I can use the array of float with Clojure? Or am I misunderstanding something?


Like how to print the array?


i believe vec can take arrays and knows how to make PersistentVectors from them


Yes that work, thanks a lot!

👍 5

I added an entry into clojuredocs to make it more visible

parens 10

(into [] f) works as well (with f a Java array of floats)


I need a way to use partition-all with a step of 1 but as a transducer... is there some way to get this by composing the transducer producing functions available in clojure.core or am I best off just sort of "copying" the transducer portion of the partition-all source code to meet my needs


whats a good http client that allows a callback per chunk for streaming requests?


@jjttjj You can use the partition from the xforms library.

(require '[net.cgrand.xforms :as xfs])

(= [[0 1 2] [1 2 3] [2 3 4]]
   (into [] (xfs/partition 3 1) (range 5)))


@madstap thanks! I just found this a minute before your response


is there a trick to turn a clojure form into a list recursively at macro-time?



(defn foo [])
(defn bar [])
(defn baz [])

(my-macro (foo (bar (baz))))
;; => (#function[user/foo] (#function[user/bar] (#function [user/baz])))


@lilactown how about this: (defmacro my-macro [xs] (flatten xs)) and then "(macroexpand `(my-macro (foo (bar (baz))))" ?


ah sorry, I probably didn’t explain well. I don’t want to flatten, I want to retain the nested-ness


I just don’t want it to be evaluated


oh sorry, i misread. But in that case the macro can just return it without calling flatten, and the rest is the same


I went with this for now:

(defn listify [f]
  (if (seq? f)
    `(list ~@(map listify f))

(defmacro my-macro [& body]
  `(list ~@(map listify body)))


hey all, so nil is considering less than everything else when comparing two things. is there a value that's considered more than everything else?


across all types? seems like a tough order


the greatest number


there's the obvious

(defn my-compare [x y]
  (cond (= x y) 0
        (= x :value/max) 1
        (= y :value/max) -1
        :else            (compare x y)))


I wanted to do something like this:

(deftype MAX []
  (compareTo [this _]
(def absolute-biggest-thing-ever (MAX.))
which works for (compare MAX 3) but not the other way around. you get class cast exceptions


im probably missing something obvious but why

(meta ^:x 'x)
returns nil


'x => (quote x)


(quote x) => x


@dpsutton you have to use a custom comparator instead of relying on the default one that uses Comparable


if you attach metadata to the form (quote x), then evaluate the form and get x, the metadata isn't on x, it is still on the form from before evaluation


like the my-compare example i gave or something else?


@yedi In Clojure's clojure.core/compare implementation, is there some value that is greater than everything else? No. There is a greatest Long (Long/MAX_VALUE), and a greatest Double value (+Inf), but there is no single value that is comparable to all other values, and greater than all of them. nil is special that way.


Why? Probably because Rich new that nil-punning was going to be common in Clojure, and didn't want exceptions raised when sorting collections using clojure.core/compare that contained nil mixed with other types. That is just my guess, though.


You are free to write your own custom comparator function that does whatever you like. If for some reason there is some value you wanted to be comparable to, and greater than, all other values, it isn't clear to me what would be a reasonable choice for such a value. You could choose nil for that, but then it would be greater than all other values, not less than all other values.