Fork me on GitHub
#clojure-europe
<
2020-09-24
>
jmayaalv06:09:48

buenos dias, dzien dobry!

bastilla06:09:04

Buongiorno altogether!

plexus06:09:50

Good morning folks! One step closer to Friday... it's one of those weeks.

9
Dmytro Bunin10:09:01

the feeling when not sure if it’s russian or ukrainian

borkdude10:09:43

Czech my friend

Dmytro Bunin11:09:18

oh right there are more slav languages

ordnungswidrig12:09:30

A quite univeral expression in slavic languages, right? Spelling and details vary though?

jiriknesl12:09:20

dobrý den 🙂

thomas09:09:51

Bono estente

otfrom11:09:26

mmm... today I shall be using cond-> transient and persistent!

💣 3
otfrom11:09:58

oh, and assoc!

otfrom11:09:18

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))

otfrom15:09:06

@mpenet @ordnungswidrig @orestis @pez @raymcdermott does this seem like a legible and reasonable use of transient?

ordnungswidrig15:09:17

If speed is your concern here. 🤷

pez16:09:53

It's quite readable, I would say.

otfrom16:09:36

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

otfrom16:09:45

so there might be some other wins hidden around

plexus06:09:20

For that last true I like to use :->

🥕 3
Ben Hammond10:09:08

why not use defrecord ? it would might be less surprising... and transient stops being an issue IIRC

otfrom11:09:11

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->

ordnungswidrig12:09:06

I typically use :alwaysinstead of true for a catch-all in conds.

3
otfrom14:09:59

ooh. I like that

dominicm11:09:47

I like true too

slipset11:09:59

Why not just a persistent! around the cond->

slipset11:09:17

You don’t have to thread everything.

otfrom11:09:25

I like doing either threading or inside out

otfrom11:09:59

tho I've not got a good reason

borkdude12:09:24

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;
    }
}

borkdude12:09:53

So everytime you write (cond ... :else :foo) you actually contribute to global warming, go figure. ;P

ordnungswidrig12:09:38

Naaa, pretty sure hotspot would catch this?!

borkdude12:09:14

How to check?

ordnungswidrig08:09:41

Two tests: that one with case and one without wherr you skipped that true clause check. Criterium should be able to warmup hotspot sufficiently.

borkdude08:09:31

That's only measuring. But how can we see that hotspot is really not hitting that path anymore

genRaiy12:09:13

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

slipset12:09:45

@borkdude You should try the same for cljs.

borkdude12:09:26

cljs.user=> (str (fn [] (if :else 1)))
"function (){\nreturn (1);\n\n}"
🎉

ordnungswidrig12:09:29

Guten Nachmittag.

borkdude12:09:41

Guten vor-Feierabend

ordnungswidrig12:09:31

After work is before work.

ouvasam13:09:05

Bon après-midi !

otfrom15:09:34

I like that this is getting out of hand

otfrom15:09:38

and good afternoon

genRaiy15:09:15

I don't read threads so I'll never find out 🙂

otfrom15:09:43

@raymcdermott does this feel like a legible and reasonable use of transient? https://clojurians.slack.com/archives/CBJ5CGE0G/p1600947978004300

genRaiy15:09:50

did you already explain why you need them?

borkdude15:09:30

since you use multiple assoc! why not combine them in a single one? assoc! already has support for that

borkdude15:09:08

oh I see, it's in cond->, never mind

genRaiy15:09:22

^^^ didn't quite pass the totally legible test 🙂

genRaiy15:09:16

I know @borkdude is not such an advanced developer but still

❤️ 6
borkdude15:09:21

(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:

borkdude15:09:21

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))

otfrom16:09:19

@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)

borkdude16:09:54

yeah, seems fine to me

otfrom16:09:56

is this a reasonable use of a transient?

borkdude16:09:34

use of transients is probably reasonable if you have measurable performance benefits

otfrom16:09:47

Cool. Looks like i should measure then 😉

😝 3
genRaiy19:09:21

I like that you challenged the meaning of legibility there @borkdude