This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-21
Channels
- # beginners (73)
- # capetown (1)
- # cider (13)
- # cljsrn (4)
- # clojure (56)
- # clojure-russia (2)
- # clojure-uk (1)
- # clojurescript (50)
- # community-development (3)
- # cursive (1)
- # datomic (80)
- # defnpodcast (2)
- # emacs (2)
- # fulcro (16)
- # graphql (8)
- # hoplon (206)
- # immutant (43)
- # keechma (4)
- # lumo (4)
- # off-topic (26)
- # perun (2)
- # re-frame (2)
- # reagent (4)
- # remote-jobs (2)
- # rum (4)
- # shadow-cljs (82)
- # spacemacs (5)
- # vim (6)
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
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 foo.bar
, then it means :foo.bar/name
; if you have an alias -- (:require [foo.bar :as fb])
-- and ::fb/name
than it resolve the alias to :foo.bar/name
. Does that help?
oh, yes! It totally solves the mystery. Thank you.
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.
I found (at least) one occurence of it on github: https://github.com/smahood/re-frame-conj-2016/blob/51fe544a5f4e95f28c26995c11d64301ba9a2142/show/src/show/snippets/snippet3.cljs#L4
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
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?
(reduce
(fn [result input]
(println result input)
(if (= 2 input)
(rest result)
result))
[2 2 2]
[1 2 3])
[2 2 2] 1
[2 2 2] 2
(2 2) 3
(2 2)
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 = 1.9.0.297
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
Is ->
being part of a function name affects its semantic? In other words, what does it do?
@vincent.cantin: see https://github.com/bbatsov/clojure-style-guide#arrow-instead-of-to
Thanks. I was asking after reading this line: https://gist.github.com/Integralist/6ba8b3effc03aa47ab93#file-1-class-clj-L30
that is one of the factory functions clojure generates for you after creating a Record
(defrecord Person [name age])
boot.user.Person
(->Person :gary 12)
#boot.user.Person{:name :gary, :age 12}
(map->Person {:name :gary, :age 12})
#boot.user.Person{:name :gary, :age 12}
oh, I see. So -> still has no language meaning. That explains a lot.
(doc ->Person)
-------------------------
boot.user/->Person
([name age])
Positional factory function for class boot.user.Person.
nil
(doc map->Person)
-------------------------
boot.user/map->Person
([m__7585__auto__])
Factory function for class boot.user.Person, taking a map of keywords to field values.
nil
yes ^_^
I wonder why I miss that important bit of information. I may have missed the normal/standard learning trail.
note that Clojure is a lot more permissive in terms of symbols in names than other languages
@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))))
nil
@lockdown- it either implements IReduce/IReduceInit or it extends CollReduce
lists don't
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 java.io.Serializable 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.io.Serializable java.lang.Object clojure.lang.Obj}
+user=> (contains? (supers (class [])) clojure.lang.IReduceInit)
true
+user=> (contains? (supers (class ())) clojure.lang.IReduceInit)
false
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
it has a method called reduce https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IReduceInit.java
if you implement that interface, you implement reduce
otherwise, the reduce function accesses your data as a sequence and does the reducing itself
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
right
@noisesmith transducer make use of this too right? transducer are also primarily an optimization ?
@bronsa transducers avoid creating intermediate sequences by composing transformations into a single one, what are the other benefits?
yes, I mean they are an abstraction that lets you compose transformations, but what's the end goal?
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.
Does that help?
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.