This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-24
Channels
- # announcements (6)
- # architecture (9)
- # aws (2)
- # babashka (49)
- # beginners (160)
- # boot (19)
- # calva (9)
- # cider (16)
- # clj-kondo (17)
- # cljfx (9)
- # clojure (143)
- # clojure-australia (5)
- # clojure-berlin (1)
- # clojure-czech (3)
- # clojure-europe (64)
- # clojure-france (1)
- # clojure-italy (12)
- # clojure-nl (4)
- # clojure-spec (6)
- # clojure-uk (47)
- # clojurescript (27)
- # code-reviews (5)
- # conjure (45)
- # cursive (47)
- # datascript (2)
- # datomic (21)
- # events (1)
- # fulcro (9)
- # graalvm (4)
- # graphql (2)
- # jackdaw (22)
- # jobs (3)
- # kaocha (6)
- # london-clojurians (1)
- # luminus (4)
- # malli (19)
- # meander (136)
- # pathom (4)
- # pedestal (2)
- # re-frame (15)
- # reitit (2)
- # remote-jobs (2)
- # rum (12)
- # sci (1)
- # shadow-cljs (100)
- # spacemacs (10)
- # sql (1)
- # tools-deps (30)
- # vrac (1)
- # xtdb (30)
the feeling when not sure if it’s russian or ukrainian
oh right there are more slav languages
A quite univeral expression in slavic languages, right? Spelling and details vary though?
so... a bit of record-scrubbing
(defn scrub-record [{::keys [id birthday start end placement] :as rec}]
(let [t (transient rec)]
(cond-> t
id (assoc! ::wce/id id)
start (assoc! ::wce/report-date (t/date start))
end (assoc! ::wce/ceased (t/date end))
birthday (assoc! ::wce/birthday (t/date birthday))
placement (assoc! ::wce/placement placement)
true (persistent!))))
(def scrub-records-xf
(map scrub-record))
@mpenet @ordnungswidrig @orestis @pez @raymcdermott does this seem like a legible and reasonable use of transient?
If speed is your concern here. 🤷
it gets called for a fair few records, so I'd like it to be quick. It currently takes around 41 seconds to process the data I'm working with
why not use defrecord
?
it would might be less surprising...
and transient
stops being an issue IIRC
I feel a bit dirty about the true at the end of the (cond->)
, but I like that more than wrapping the whole thing in a ->
around the cond->
I wonder if the Clojure compiler folds this:
user=> (macroexpand '(cond :else 1))
(if :else 1 (clojure.core/cond))
into just 1
. Should look at the bytecode...
Apparently not:
user=> (clj-java-decompiler.core/decompile (fn [] (if :else 1)))
// Decompiling class: user$fn__207
import clojure.lang.*;
public final class user$fn__207 extends AFunction
{
public static final Keyword const__0;
public static final Object const__1;
public static Object invokeStatic() {
final Keyword const__0 = user$fn__207.const__0;
if (const__0 != null) {
if (const__0 != Boolean.FALSE) {
return user$fn__207.const__1;
}
}
return null;
}
@Override
public Object invoke() {
return invokeStatic();
}
static {
const__0 = RT.keyword(null, "else");
const__1 = 1L;
}
}
So everytime you write (cond ... :else :foo)
you actually contribute to global warming, go figure. ;P
Naaa, pretty sure hotspot would catch this?!
Compare?
Two tests: that one with case and one without wherr you skipped that true clause check. Criterium should be able to warmup hotspot sufficiently.
That's only measuring. But how can we see that hotspot is really not hitting that path anymore
would be nice if all the stuff that @mfikes has done in CLJS to optimise and short-circuit these conditions were brought back into Clojure
Guten Nachmittag.
After work is before work.
@mpenet @ordnungswidrig @orestis @pez @raymcdermott does this seem like a legible and reasonable use of transient?
@raymcdermott does this feel like a legible and reasonable use of transient? https://clojurians.slack.com/archives/CBJ5CGE0G/p1600947978004300
since you use multiple assoc! why not combine them in a single one? assoc! already has support for that
(deftype Foo [m]
clojure.lang.Associative
(assoc [this k v]
(if v
(Foo. (assoc m k v))
this))
clojure.lang.ILookup
(valAt [this k]
(get m k))
Object
(toString [this]
(str m)))
(let [v (assoc (Foo. {})
:a false
:b nil
:c 3
:d 4)]
(prn v)
(prn (get v :c)))
#object[user.Foo 0x695a69a1 "{:c 3, :d 4}"]
3
:thinking_face:we actually have a function for this in our codebase at work (uses transients):
(defn nn-hash-map
"Like c.c/hash-map but does not include false or nil values."
[& keyvals]
...
ret))
@borkdude I've written things like that in the past. This feels like a reasonably quick use of the std lib (tho I've only done it this way today so I'm not devoted to the idea)