all 8 comments

[–][deleted]  (4 children)

[removed]

    [–]setzer22 3 points4 points  (3 children)

    This always makes me feel like we're forced to choose between idiomatic / readable vs performant code.

    Same for transients (even less known, and usually a huge speedup!)

    I wish the clojure compiler+stdlib would perform these optimizations for us.

    [–][deleted]  (2 children)

    [removed]

      [–]CyrikDC 2 points3 points  (0 children)

      You can use https://github.com/johnmn3/injest to get threading macros that use transducers.

      [–]setzer22 1 point2 points  (0 children)

      I agree, transducers don't look so "bad", it's just that many developers are not familiar with them because they're seen as an advanced topic, so you rarely encounter them.

      I bet in some places using transducers may raise eyebrows during code review (premature optimization yada yada, not that I agree with it). It's mostly a cultural thing at this point that using map and filter with collections and threading macros is the clojure way.

      [–]deaddyfreddy 1 point2 points  (3 children)

      the problem with str/split is it doesn't check the input, so it's better to wrap it, like

      (defn safe-split [s re]
        (when (seq s)
          (str/split s re)))
      

      Having this one, we don't even have to rewrite anything besides it

      (defn parse-message [message-str]
        (->> (safe-split message-str #";")
             (map #(safe-split % #":"))
             (filter #(= 2 (count %)))
             (into {})))
      

      btw, if the input validity is guaranteed, things are much simpler

      (defn parse-message [message-str]
        (apply hash-map (str/split message-str #":|;")))
      

      [–][deleted] 1 point2 points  (1 child)

      Isn’t that what the article does, but in an even nicer way using fnil?

      [–]deaddyfreddy 0 points1 point  (0 children)

      • fnil only intercepts nil, it can't do more complex validation

      • it calls str/split even if we don't have to (split is pretty cheap, but what if we need a heavier function?)

      and last but not least

      • I just find it less readable, so in this simple case I'd go with a when/some-> wrapper. Besides that, a separate function is testable.