This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-04-30
Channels
- # aleph (12)
- # beginners (23)
- # boot (12)
- # cider (40)
- # cljs-dev (8)
- # cljsrn (20)
- # clojars (1)
- # clojure (122)
- # clojure-canada (2)
- # clojure-dev (21)
- # clojure-gamedev (2)
- # clojure-italy (3)
- # clojure-nl (12)
- # clojure-norway (1)
- # clojure-sanfrancisco (3)
- # clojure-spec (59)
- # clojure-uk (114)
- # clojurescript (50)
- # clojurex (1)
- # cursive (2)
- # datascript (2)
- # datomic (26)
- # emacs (5)
- # fulcro (19)
- # garden (1)
- # hoplon (54)
- # leiningen (42)
- # luminus (14)
- # off-topic (24)
- # om (5)
- # onyx (7)
- # re-frame (2)
- # reagent (31)
- # reitit (3)
- # ring-swagger (39)
- # shadow-cljs (8)
- # sql (3)
- # tools-deps (13)
Can anyone point me to examples of using transduce
where map
is f
and the xforms
are the functions called by map
? I'm thinking of something like (map #(xf3 (xf2 (xf1 %))) coll)
=> (transduce (comp xf3 xf3 xf1) map coll)
where coll
is presumably nested and transduce
returns it flat.
(map #(xf3 (xf2 (xf1 %))) coll)
becomes (sequence (map #(xf3 (xf2 (xf1 %)))) coll)
or (transduce (map #(xf3 (xf2 (xf1 %)))) into [] coll)
You can substitute (map #(xf3 (xf2 (xf1 %))))
by (comp (map xf1) (map xf2) (map xf3))
(map (comp xf3 xf2 xf1))
is another option (beware of composition order being different this time)
@sophiago your whole transformation is just a bunch of map
? (it doesn’t ring quite right with
> where coll
is presumably nested and transduce
returns it flat.
It's a pattern I use a lot. Basically applying different functions to each level of nesting that end up flattening them.
but (trying to understand) if you do (map #(xf3 (xf2 (xf1 %))) coll)
, xf3 must returns a single element and 99% of the flattening is done by #(xf3 (xf2 (xf1 %)))
, no?
I’m not following, if you could come up with a concrete (runnable) example it would help me a lot
Hmm... this may fit into how I just realized @cgrand's second, prettier, example probably wouldn't do what I want like the first would
A practical example would neither be minimal nor reproducible so I'm not sure how much it would help in explaining the pattern
@dominicm but then if you chain (comp cat (map xf1) cat (map xf2) cat (map xf3))
you can merge maps and cats into a mapcat
(i also do realize i could use map-indexed
but purposefully changed it to keep them all unary)
More a weird experiment tbh. But it only adds lines 10 and 11 plus the calls to first
and second
in xf1. Otherwise, this looks much more legible than the version on my master branch where none of these are lifted.
What I would love, but am not going to do right now, is to write a macro where I can inline the xforms and have each level of mapping be like %1
, %2
, %3
, etc.
Yes. It's a transducer that takes and returns data.avl/sorted-map-by
with a custom comparator
Also, I'd have to give some thought to how to handle line 18 even if I could get this to work with transduce
The issue now is with xf1
though. I should try rewriting it without the literal syntax and inlining it...
(defn chain2
[f g order]
(let [f (nth (iterate add-dim f)
(dec (long (count (ffirst g)))))
f' (diff-unmixed1 f order 1)
g' (diff g order)
xf1 #(*' (long (Math/pow 10 %1)) %2)
xf2 #(get g' (transduce (map-indexed xf1) +' %))
; here I assume mul can be changed to a binary form and is commutative
xf3 (transduce (map xf2) mul (multi-compose (nth f' (dec (count %))) g) %)]
(->> order
partition-set
(map xf3)
(apply add))))
I think I just need to play the manual step-through debugging game and my version above could be used with transduce
if I wanted
I can start from (#(map (map (map xf1 %))))
and the types are sane...composing these this way becomes rough at just one level
(defn partition-set [n] (->> (range 1 (inc n)) clojure.math.combinatorics/partitions))
frankly, i was surprised composing function literals like this works so i'm guessing either the order of composition is off or there's capture going on
logically, i don't see why else (sequence (partial xf3 (partial xf2 xf1)))
wouldn't work
Well, confirming my (very broad) hypothesis about composition order: if I start eliminating lines after what should be the last map
I get different errors. Same with count
throwing.
I think it would be explanatory to rewrite the partials
as literals: (partial xf3 (partial xf2 xf1))
should be #(xf3 (partial xf2 xf1) %)
but instead it seems like (partial xf3 (xf2 #(xf1 %)))
Currently each xform is binary, but the first argument should be substituted in a different order from the second
So with partial
the functions compose correctly, but are called incorrectly (I think?)
you have partitions-set wihich generates a 3-level deep structure (all-partitions, partition, component)
and you want to perform a computation in 3 stages, at each stage folding the deepest level
And to be clear, it does work...I'm just rewriting it a gazillion ways because I'm a bit insane like that
idk, at this point i surely need to step away from the keyboard until the answer hits me
but i'm very impressed you've held on to the point of even understanding the function without 500+ lines of context 🙂
have you worked with some langs of the APL family? this deep map and way if thinking reminds me of operator ranks etc.
Other than Clojure, I primarily use Haskell so before heading down this road I slapped my head and thought "lenses" ...which is what Specter is, really. But this is really an exercise in lambda syntax so I'd prefer to avoid that.
@sophiago so far I can rewrite it like this:
;; mul and add needs to be transduce-friendly: 0, 1 and 2 arities
(defn chain2
[f g order]
(let [f (nth (iterate add-dim f)
(dec (long (count (ffirst g)))))
f' (diff-unmixed1 f order 1)
g' (diff g order)
xf1 #(*' (long (Math/pow 10 %1)) %2)
xf2 #(transduce (map-indexed xf1) +' %)
xf3 #(transduce (comp (map xf2) (map g'))
mul (multi-compose (nth f' (dec (count %))) g) %)]
(transduce (map xf3)
add (partition-set order))))
each stage being a call to transduce to map and fold in one go
Note that I moved g'
call from xf2 to xf3 to make this pattern more regularThanks so much. I'll probably end up using that just because, well, quality. But it doesn't solve the theoretical problem that's driving me now, i.e. you still have each xform calling one another in the let
.
if you want to avoid that you are going to allocate a lot of cons cells. I don’t know if I stil have it around
Hello, guys. We've had recent issues with http-kit
client and SNI (Server Name Indication) so we decided to migrate to clj-http
, now I'm just trying to figure out if it fully supports SNI, and also if we can rely on the underlying retry mechanism or if we need to wrap the request with our own retry - any tips?
@sophiago I would personally entertain rewriting partitions
to perform the computation on the fly 😉
I totally was about to before I saw using the combinatorics library would almost be a drop-in. But I'm really convinced that has nothing to do with this issue. I would need to desugar the let
to think it through, but I'm guessing it bypasses the compiler's disallowance of nested function literals (oddly enough forking it that way is what drove me down this road, although this I'm not using that fork for this exercise) and the results are not how I reasoned them to be. I suppose I could test that using fn
s with different bound variable names
(totally untested)
(defn dive [depth f & args+x]
(let [args (into [f] (butlast args+x))
x (last args+x)
d (fn d [depth]
(fn [x]
(if (pos? depth)
(map (d (dec depth)) x)
(apply f (conj args x)))))]
((d depth) x)))
(defn chain2 [f g order]
(let [f (nth (iterate add-dim f)
(dec (long (count (ffirst g)))))
f' (diff-unmixed1 f order 1)
g' (diff g order)]
(->> order
partition-set
(dive 2 map-indexed #(*' (long (Math/pow 10 %1)) %2))
(dive 2 reduce +')
(dive 2 g')
(dive 1 reduce mul (multi-compose (nth f' (dec (count %))) g))
(apply add))))
Sorry, I didn't mean to spend so long on that and had to try and get some sleep. I meant that in a literal sense: Clojure doesn't allow nested function literals and there are two lines in the compiler that enforce this. That's what this whole exercise of rewriting a working function was essentially about for me. I realized I could just lift the lambdas, but then they started to compose oddly.
@triss, so I think that using a :type
key is great unless you run into perf problems (or you're implementing your own data type)
there was a great flowchart on when to use maps vs defrecords but I can't find it now
@pesterhazy https://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
@d._.b exactly 🙂
multimethods are good for when you need polymorphism across one method protocols allow you to have polymorphism across a bundle of methods
or just use multiple multimethods
And protocols only allow for dispatch by the type of the first argument.
Kotlin can output JVM code and JS code. *.cljc can output JVM code and JS code. Is there any example of mixing Kotlin/Clojure where both codebases generates both JVM and JS code, and can interop on both platforms?
@triss Keep in mind that multimethods let you dispatch on anything you want, while records only look at the type. Sometimes can help make the choice for you.
javax.json is newish (I am not sure if it was introduced in java 7 or 8 ), and it is part of java EE, which if I recall, is bundled with jdks, but not all jres
I'm running both versions on my laptop, so I assume it's the same version of java?
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
oh you know what, I included javax.json (https://mvnrepository.com/artifact/org.glassfish/javax.json/1.1.2) in deps and it worked