Fork me on GitHub

that's great that you can make it work with destructuring, but the performance argument is another reason to use core.match instead, since it's quite optimized

Vincent Cantin03:01:54

Hi. I am not yet clear about the difference between :name and ::name. Is ::name still considered just a normal keyword with a different name? Why people are using ::name instead of :name sometimes?


@vincent.cantin the :: prefix means "auto-resolve the namespace qualifier": if you have ::name in the namespace, then it means; if you have an alias -- (:require [ :as fb]) -- and ::fb/name than it resolve the alias to Does that help?

Vincent Cantin03:01:10

oh, yes! It totally solves the mystery. Thank you.

Vincent Cantin03:01:47

Is there a difference between (.getElementById js/document "app") and (js/document.getElementById "app") (both seem to work). Which one should be preferred?


The former is what I've seen in ClojureScript. I'm a little surprised that the latter works.


(.method object arg1 arg2) is the normal Clojure(Script) call format for interop with the OOP host.


Interesting... I expect it works by accident, as a parallel for (SomeThing/staticMethod arg1 arg2) ?


I hear tell there's at least one place where it was used in a Rich Hickey commit - but there's an example mfikes showed where if you use the normal syntax it can give you a clear error message about a binding, and if you use the pseudo-interop syntax it just fails with an undefined at runtime


iirc it involved shadowing without a warning

Vincent Cantin04:01:54

I also found (. js/document getElementById "app") on github, which works too (I tested it).


that is what (.getElementById js/document "app") expands to - it's lower level but easier to use from a macro if you are generating an interop call


Hey! Is there a way to map a collection while reducing another one arbitrarily while injecting it onto the mapped one? eg. I have a vec [1 2 3] and I want o map it while injecting in its context all the contents of [2 2 2], I want to do so that when iterating through 2 (first vec) it matches the first 2 of the second vector and removes it as to when iterating through 3 I`ll only have [2 2] as a context for 3 to work with.


i'm confused by what you need... usually if there are too many things that i need done to a vector, i'd split it into a few functions


@igor.larcs does this work for you?

 (fn [result input]
   (println result input)
   (if (= 2 input)
     (rest result)
 [2 2 2]
 [1 2 3])
[2 2 2] 1
[2 2 2] 2
(2 2) 3
(2 2)


@sundarj it might! I'm gonna test it against my problem


let me know! 🙂


Hi all, a question on using deps.edn with a git library: I’ve created an empty project with just a deps.edn:

{:deps {org.clojure/data.priority-map
        #_{:mvn/version "0.0.7"}
        {:git/url "" :sha "043a45342be7fbfa6cfa6363e522fcffeb3fd7bc"}}}
With the mvn coordinate, clj works fine. But with the git coordinate, it produces:
version      =
install_dir  = /usr/lib/clojure
config_dir   = /home/martin/.clojure
config_paths = /usr/lib/clojure/deps.edn /home/martin/.clojure/deps.edn deps.edn
cache_dir    = .cpcache
cp_file      = .cpcache/2317405680.cp

Refreshing classpath
Error building classpath. nil

Vincent Cantin16:01:07

Is -> being part of a function name affects its semantic? In other words, what does it do?


that is one of the factory functions clojure generates for you after creating a Record


(defrecord Person [name age])

(->Person :gary 12)
#boot.user.Person{:name :gary, :age 12}

(map->Person {:name :gary, :age 12})
#boot.user.Person{:name :gary, :age 12}

Vincent Cantin16:01:29

oh, I see. So -> still has no language meaning. That explains a lot.


(doc ->Person)
([name age])
  Positional factory function for class boot.user.Person.

(doc map->Person)
  Factory function for class boot.user.Person, taking a map of keywords to field values.


glad to have helped 🙂

Vincent Cantin16:01:00

I wonder why I miss that important bit of information. I may have missed the normal/standard learning trail.


well, if you've never seen it before, it's natural to wonder what it means 🙂


note that Clojure is a lot more permissive in terms of symbols in names than other languages


(def !?*-><%$#& 2)


Ah, upgrading to fixed the above problem.


What's makes a collection reducible, that it knows how to reduce itself?


@lockdown- read the source:

boot.user=> (source reduce)
(defn reduce
  "f should be a function of 2 arguments. If val is not supplied,
  returns the result of applying f to the first 2 items in coll, then
  applying f to that result and the 3rd item, etc. If coll contains no
  items, f must accept no arguments as well, and reduce returns the
  result of calling f with no arguments.  If coll has only 1 item, it
  is returned and f is not called.  If val is supplied, returns the
  result of applying f to val and the first item in coll, then
  applying f to that result and the 2nd item, etc. If coll contains no
  items, returns val and f is not called."
  {:added "1.0"}
  ([f coll]
     (if (instance? clojure.lang.IReduce coll)
       (.reduce ^clojure.lang.IReduce coll f)
       (clojure.core.protocols/coll-reduce coll f)))
  ([f val coll]
     (if (instance? clojure.lang.IReduceInit coll)
       (.reduce ^clojure.lang.IReduceInit coll f val)
       (clojure.core.protocols/coll-reduce coll f val))))


@sundarj I understand reduce


but what collection can't reduce itself?


@lockdown- it either implements IReduce/IReduceInit or it extends CollReduce


@bronsa what collection doesn't implement those interfaces?


it's straightforward to find outin a repl

+user=> (supers (class []))
#{clojure.lang.IPersistentCollection clojure.lang.APersistentVector clojure.lang.IReduce clojure.lang.IFn java.lang.Comparable clojure.lang.IHashEq clojure.lang.IPersistentVector clojure.lang.IMeta java.util.List clojure.lang.Seqable clojure.lang.IObj java.util.concurrent.Callable java.util.Collection clojure.lang.IReduceInit clojure.lang.IEditableCollection clojure.lang.ILookup clojure.lang.Sequential clojure.lang.Counted clojure.lang.Indexed java.util.RandomAccess clojure.lang.IPersistentStack java.lang.Iterable clojure.lang.Associative clojure.lang.Reversible java.lang.Runnable java.lang.Object clojure.lang.AFn clojure.lang.IKVReduce}
+user=> (supers (class ()))
#{clojure.lang.IPersistentCollection clojure.lang.IHashEq clojure.lang.IMeta java.util.List clojure.lang.Seqable clojure.lang.IObj java.util.Collection clojure.lang.Sequential clojure.lang.Counted clojure.lang.IPersistentList clojure.lang.IPersistentStack java.lang.Iterable clojure.lang.ISeq java.lang.Object clojure.lang.Obj}
+user=> (contains? (supers (class [])) clojure.lang.IReduceInit)
+user=> (contains? (supers (class ())) clojure.lang.IReduceInit)


why does (reduce + 0 '(1 2 3 4 5)) works then?


because you can reduce things that don't implement IReduceInit


IReduceInit is an optimization that reduce uses if available


it lets the collection reduce itself, instead of reduce doing it


so what does those interfaces actually?


if you implement that interface, you implement reduce


otherwise, the reduce function accesses your data as a sequence and does the reducing itself


don't get it haha, for example, why range knows how to reduce itself?


like reduce itself to what?


it's for performance - range can reduce with your function in a way that's faster than the reduce function doing it by asking for the next item repeatedly


the reduce method in IReduceInit requires an initial value and a function - so it reduces using those arguments, and should have the same result the reduce function would have


I see, ok its mostly an optimization, eliminates intermediate results contrary to reduce function doing it by asking for the next item repeatedly as you said


right - I'd say it's more than "mostly" an optimization - it would be possible for some version of IReduceInit forsome collection to do something reduce wouldn't do, but I don't think it would be a good idea


ok, for me now, since I'm just learning, and don't care much about performance yet, a simple answer is that reduce will performance better on reducible collections than in no reducible collections


@noisesmith transducer make use of this too right? transducer are also primarily an optimization ?


no transducers are not an optimization, they're a different abstraction


@bronsa transducers avoid creating intermediate sequences by composing transformations into a single one, what are the other benefits?


because they compos transformations that are independent of input or output sources


you can use them lazily, eagerly, sequentially, in parllell, in async contexts etc


yes, I mean they are an abstraction that lets you compose transformations, but what's the end goal?

Drew Verlee22:01:54

I think of the goal of transducers as identifying that the function can be separated from the input and output. The transducer is function that performs the transformation without knowing the input it operates over and the output collection it creates. By reducing coupling (input and output) were able to create more re-suable abstractions and more high level abstractions.

Drew Verlee22:01:06

Does that help?

Drew Verlee22:01:15

In immediate benfiet of this is that it allows a function, which is a series of transformations, to be used as a be passed as an argument.


they're not just an optimzation to remove intermediate sequences


thought they were just used eagerly


user=> (take 2 (sequence (map inc) (range)))
(1 2)
this is lazy