This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-30
Channels
- # aleph (1)
- # announcements (7)
- # aws (4)
- # beginners (52)
- # calva (11)
- # cider (20)
- # clj-kondo (36)
- # clojure (53)
- # clojure-austin (1)
- # clojure-brasil (1)
- # clojure-conj (1)
- # clojure-europe (27)
- # clojure-italy (17)
- # clojure-nl (11)
- # clojure-norway (2)
- # clojure-spec (41)
- # clojure-uk (39)
- # clojuredesign-podcast (2)
- # clojurescript (22)
- # clojutre (14)
- # community-development (24)
- # cursive (6)
- # data-science (1)
- # datomic (38)
- # duct (3)
- # figwheel-main (8)
- # fulcro (34)
- # funcool (8)
- # jackdaw (3)
- # jobs (2)
- # off-topic (84)
- # pathom (3)
- # re-frame (4)
- # shadow-cljs (8)
- # tools-deps (5)
- # vim (7)
If you mean the ones in the clojure.core namespace, included as part of Clojure, most functions are pure functions, but not all. Any particular transducer you are curious about?
Here are functions that return transducers whose implementations I believe are stateless: map, cat, mapcat, filter, remove, take-while, replace, keep, halt-when, random-sample Stateful: take, drop, drop-while, take-nth, distinct, interpose, partition-by, partition-all, map-indexed, keep-indexed, dedupe. I did not notice any in my stateless list that contain any functions that are themselves stateful, unless you want to consider random number generation stateful, which in a sense it is because it is implemented by reading and modifying the state of a pseudo-random number generation algorithm. I put it in the stateless list because except for that, which one ideally hopes looks "independent" from one call to the next, it is stateless.
take-while feels stateful because it has to know to stop sending output. For a finite stream it can be made stateless. It isn’t clear how this could be stateless for an infinite stream.
Transducers are process transformations where a process is a reducing fn to be used by something that implements IReduceInit
, which supports reduced
as the early termination mechanism. take-while
uses that to stop the process in the middle. Here's the source of the transducer-returning arity of take-while
:
(defn take-while
"Returns a lazy sequence of successive items from coll while
(pred item) returns logical true. pred must be free of side-effects.
Returns a transducer when no collection is provided."
{:added "1.0"
:static true}
([pred]
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (pred input)
(rf result input)
(reduced result)))))))
As you can see here, the init and the completion arities of the returned process are as usual, but in the input-consumption step, take-while
bails out using reduced
. Please watch Rich Hickey's Transducers talk at Strange Loop if you're confused about what I mean by a "process"
All take while needs is whether the current input satisfies the predicate, and not any information about previous inputs, so no state is necessary. take
on the other hand needs to know how many more things it needs to take, which means it needs to keep track of how many things it already took. And that requires state.
I think I’m using these a little differently. I’m using transducers in a stream processing application where each call to into []
only sees the current input.
I don’t think take-while
can work as intended when the collection is of size 1, but maybe there is better way to convey these from the underlying Kafka topic.
All transducers have the ability to stop producing new elements. I don't know the implementation details, but I believe that is how both halt-when and take-while stop producing new elements.
Well, when I say "all transducers", I do not mean that all of the ones in clojure.core have this ability -- I just mean that whenever one writes a transducer, the capability is available to write it so that it stops propagating elements from its source.
Alex's talk at ClojuTRE about lessons learned and spec2: https://www.youtube.com/watch?v=KeZNRypKVa4&feature=youtu.be
personally, my favorite talk was Dave's about essential complexity that's impossible to disentangle and how to deal with it (if i understand it right, I think I need a re-watch it) https://www.youtube.com/watch?v=xYqWREPb3Lc
I missed that one, I need to watch it. Was talking to some folks in the hallway tracks.
At first glance it sounded like "Don't bother trying to achieve simplicity". But perhaps a better takeaway would be that some systems are inherently complex and we can't hope to simplify them because we would only obscure things. However, I think we should strive to avoid creating complex systems in the first place.
Dave’s point (also incorporated in his Cynefin framework) is that there are different domains in which different methods are appropriate. He emphasized that there are domains, in which methods that try to establish linear causality that rely on repeatability of simple cause & effect chain don’t work, you need a different perspective. His talk is less about how we should write software, more about how to classify problems (simple, complicated, complex) and what are the appropriate methods to tackle them.
Applied Complexity Science is an amazing field. I'd recommend the writings & math papers of Nassim Taleb as an entry point. Very closely aligned to Dave's conclusions.
Is there a transducible equivalent of clojure.core/some fn?
@karol.wojcik Maybe you can roll your own like this?
(transduce (map inc) (completing (fn [acc x] (when (pos? x) (reduced x)))) 0 (range -10 10))
1
@karol.wojcik You can also look at https://github.com/cgrand/xforms, which has a some reducing fn
@karol.wojcik (comp (keep pred) (take 1))
?
Nice!
Thank you guys!!
Is there a way to force spec to recursively conform an s/or
over a bunch of multi-specs?
don't understand the question, can you give an example?
also maybe in #clojure-spec instead
Hi! Is there an alternative to Plumatic Schema that isn’t clojure.spec? (a popular alternative)
maybe if you shared why those weren't a good match for you, it would help trigger alternatives
@alexmiller oh it’s not about them being a bad match, I just want to know if I am missing another popular lib
spec-tools is popular, not an alternative but a lib that builds on top of spec. https://github.com/metosin/spec-tools/blob/master/docs/02_data_specs.md
just for data regex on colls: https://github.com/cgrand/seqexp
possibly core.typed as well, depending on your goals
seqexp is something which I almost wanted to implement (by extracting parts from spec), thanks for sharing
if I'm not mistaking, seqexp is older than spec. was using regexes for spec inspired by this maybe?
not the inspiration, but we did look at it as one example while implementing (can't remember if it was before or after the current impl)
as always, cgrand does great work
iirc there were a couple choices in seqexp that were not aligned with what we wanted to do, but it's a good lib
I really like parts of truss and herbert too