This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-28
Channels
- # announcements (1)
- # beginners (205)
- # calva (30)
- # cider (5)
- # cljdoc (25)
- # cljs-dev (2)
- # clojure (119)
- # clojure-brasil (5)
- # clojure-conj (7)
- # clojure-europe (2)
- # clojure-hamburg (7)
- # clojure-italy (14)
- # clojure-nl (2)
- # clojure-russia (13)
- # clojure-spec (79)
- # clojure-uk (58)
- # clojurescript (54)
- # core-logic (2)
- # core-matrix (2)
- # cursive (40)
- # datascript (2)
- # datomic (18)
- # duct (2)
- # emacs (14)
- # figwheel (3)
- # figwheel-main (7)
- # fulcro (30)
- # funcool (1)
- # graphql (10)
- # jobs (1)
- # juxt (13)
- # lumo (1)
- # mount (1)
- # off-topic (56)
- # other-languages (2)
- # pedestal (17)
- # powderkeg (2)
- # protorepl (2)
- # re-frame (10)
- # reagent (1)
- # reitit (7)
- # ring-swagger (10)
- # schema (2)
- # shadow-cljs (70)
- # spacemacs (13)
- # specter (4)
- # sql (9)
- # tools-deps (26)
if you have something like (into [] a-transducer (range n))
- does the range sequence gets created and cached here?
range returns a thing that both implements Iterable and IReduce, both of which have custom fast paths when processed via reduce, which into does
looking at the source, in these case is using transduce instead of reduce but yeah, same concept
and range doesn’t actually cache anything
@alexmiller if you do (map foo (range n))
- the values of range don't get stored in memory?
that’s not the code you have above
and what happens is much different
when using a range as a reducible (as with into
), the whole thing just boils down to a single loop over the data and no values are cached in memory
even when used as a seq, it builds chunks that store only the start/step/count values, not the actual data values
implements IReduce
and has a reduce method
for a long-only range for example: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LongRange.java#L229-L238
the into
example above is primarily running this loop
where f is the transducer
and val is []
this is not the only path to being reducible, but it’s the fastest
you can also participate in the CollReduce protocol
vectors and maps also know how to do this
and the results of cycle
, iterate
, repeat
no, not currently
#(or (instance? clojure.lang.IReduceInit %) (satisfies? clojure.core.protocols/CollReduce %))
@alexmiller that reminds me, has there ever been any consideration of a for
variant for producing a similar reducible/iterable? I remember poking around a while back thinking there'd be one. I figure it just doesn't come up enough as an optimization to be necessary, particularly since you can usually achieve the same thing with eduction, iterate, etc, but while we're talking about it....
I’m not sure that makes sense
reducible gets it power by eagerly consuming the source, so doesn’t make sense to make one reducible from another
not sure what that would mean, but no :)
the sequence
function, when used with a transducer makes an incrementally computed sequence
mostly it's just there so you can generate a lazy-sequence by composing transducer functions (map, filter, take, etc) without having to use them as lazy sequence functions - saves the overhead of the intermediate sequences
there are some differences from lazy sequences as each intermediate step is fully computed
transducers are a push model, not a pull model
so for example, lazy sequences can compute infinite intermediate sequences and you can use as much of that as you like
but sequence
with a transducer would work forever producing the intermediate step
most commonly this comes up with mapcat
oh, yeah, ike if you had a filter that's never satisfied it would run forever trying to get to a value that satisfies the filter even if you only try and get a single item from it
well, that may be true of both
like (take 2 (mapcat #(repeat 1000 %) (range 5)))
only needs to produce 2 values
actually, that explains why the core transducer functions don't just do, like, ([pred col] (sequence (filter pred) col))
for the lazy-seq-producing form, instead using lazy-seq directly
but (into [] (comp (mapcat #(repeat 1000 %)) (take 2)) (range 5))
will produce 1000 values and give you 2
@alexmiller actually, thinking about this further, are you sure this is the case? take
short-circuits the whole pipeline (even to the point of preventing chunked loading when using sequence
) - (into [] (comp (mapcat #(repeat 1000 %)) (map #(do (println %) %)) (take 2)) (range 5))
only prints 2 lines, for example, as does (sequence (comp (mapcat #(repeat 1000 %)) (map #(do (println %) %)) (take 2)) (range 5))
(into [] (comp (mapcat (fn [v] (iterate #(do (println %) %) v))) (take 2)) (range 5))
also successfully terminates despite the infinite iteration in the mapcat, printing 1 line
My read on it is that while transducers are push-based, the fact that it's all driven by a reductio pipeline lets you nevertheless control it via reduced
, avoiding realizing values that will never be used except in unavoidable situations that also apply to lazy sequences. At least, I can't think of one that would apply to a transducer pipeline + sequence
but not a lazy-seq
both seqs and transducers have their place
oh sure. I just mean, when I write my own custom transforms, I like to follow teh same pattern as core and make them work either as transducers or sequence functions based on arity. but I usually just take the shortcut of using sequence
. this conversation has me reconsidering that, though
yeah, I wouldn’t do that
they really are different
yeah, I see why it's a bad idea now that you point out the effects of the push behavior. thanks
@alexmiller your into
and concat
example was to demonstrate what the sequence
fn does with a transducer? that it fully computes intermediate values
finding a use case for sequence
, is like when you want a lazy result of intermediate steps
that use case is imo small
Has anyone here successfully deployed a “create-react-app” app with ring? I’m having trouble to work with registerServiceWorker.js
, it says on the console log:
No internet connection found. App is running in offline mode.
Is https://www.reddit.com/r/Clojure/comments/z0o6u/robbit_reddit_apibots_in_clojure/ state of the art for getting started with "write a reddit bot in clojure" ?
the github link doesn't work, and the author doesn't seem to appear either
Well, adding https://github.com/ThatGuyHughesy/creddit to https://github.com/yetibot/yetibot is on the list.
Hi. I'm trying to write a test with cljs.test. I want to have all the names from my main module right available in the test module. Without prefixes or explicit enumeration. Can I do that?
Basically (:use [app.main :only [multiply]])
works while (:use [app.main])
. While the docs say that both are correct.
Still doesn't compile Only :as, :refer and :rename options supported in :require / :require-macros;
This might also be useful: https://gist.github.com/ghoseb/287710/
It most likely is an issue with bundle size — but you could ask on #clojurescript for details.
As a “workaround”, you could do (:require [app.main :as a])
and use a/foo
, a/bar
. It’s an extra two characters on every occurrence, so just a little bit more onerous than the naked case.
I agree though that sometimes for tests it’s nice to be able to just bring everything in.
How do you guys do Profile Clojure projects? I have tried JVisualVM bur it gives me some cryptic info. Please advice.
Can you share some more info? What’s the cryptic info look like, what are you trying to measure?
https://imgur.com/a/sPlHqKl This is what I mean. Nothing resembles my actual code.
I’m not an expert on this, nor do I know if there’s a better way to do profiling on Clojure, but with a little effort this output is readable: clj_xml_validation.core$validator_from_schemas.invokeStatic
is equivalent to a call to function (clj-xml-validation.core/validator-from-schemas ...)
importer.integrity$differing_contexts_for_global_ids$iter_4304__4308$fn__4309$fn__4314.invoke
is a little bit trickier, as it probably involves some anonumous function inside importer.integrity/differing-contexts-for-global-ids
.
iapetos has function instrumentation: https://github.com/xsc/iapetos#function-instrumentation
The hot spots can be confusing because you're not seeing a tree of method calls. Look in the Threads tab or Thread CPU time (can't remember if both of them have the method call tree).
Another issue which I have run into with profiling in Clojure is that laziness can give you misleading results. i.e. If I construct a large lazy sequence in an inefficient manner, then I will not see the CPU spike at construction time (where the problem is), but whenever the list is actually evaluated and used
Hi guys, ever since I've upgraded from AWS Java SDK V1 to V2, I've been getting about 80 lines of warnings about version ranges. From reading [1] I understand that this issue is not going to be resolved soon, but is there anything I can do to suppress these messages for just these dependencies? [1] https://github.com/technomancy/leiningen/issues/2251