top | item 33020716

(no title)

balefrost | 3 years ago

I can't speak about Haskell, but Clojure's lazy sequences also generate a lot of intermediate allocs.

For example, here's Clojure's implementation of `map`[1]. It internally uses `cons` to build a cell[2] and `map` to recursively walk the collection (but all wrapped up in `lazy-seq` to delay evaluation).

Transducers[3] do help with this if you are applying a stack of collection transformations. But, and this is just my opinion as a very occasional Clojure user, transducers are harder for me to grok and so I generally avoid using them. If I was doing performance critical work, I might try to build up a better mental model.

My biggest complaint about the Java streams API is that it makes it hard to write your own stream transformation functions. Or rather, you can, but then calling them is awkward. You generally transform a Stream by calling instance methods - e.g. `myStream.map(::f)`. But since Java doesn't have extension functions, there's no way for you to make a custom function callable in the same way as the built-in functions. I ended up writing a small shim to build a stream pipeline without using member functions. You would use it something like this:

    newPipeline(stream)
        .then(map(::mapFn))
        .then(filter(::filterFn))
        .then(customTransform())
        .collect(Collectors.toList());
Contrast that to Clojure, where everything's a function:

    (into []
      (customTransform
        (filter filterFn
          (map mapFn collection))))
Or (using the threading macro, I think this is right)

    (->> collection
      (map mapFn)
      (filter filterFn)
      (customTransform)
      (into []))
Or (using transducers, I'm really not sure if this is right)

    (into []
      (comp
        (map mapFn)
        (filter filterFn)
        (customTransducer))
      collection)
        
                      
[1] https://github.com/clojure/clojure/blob/2b3ba822815981e7f769...

[2] https://github.com/clojure/clojure/blob/2b3ba822815981e7f769...

[3] https://clojure.org/reference/transducers

discuss

order

No comments yet.