Remix.run Logo
evdubs 6 hours ago

Threading macros are nice, though, right?

https://docs.racket-lang.org/threading/introduction.html

whartung 3 hours ago | parent | next [-]

They're nice, but they're not the same thing.

The threading macros are (as I understand it) pure sugar.

Turning (-> (gather my-list) uppercase-list sort) into (sort (uppercase-list (gather my-list))).

In contrast to, say, Java (I can't speak to the code above):

        List<Things> things = thingIds.stream()
                .map(model::findThing)
                .filter(Objects::nonNull)
                .toList();
These are streamed. This is pretty much a pipe structure, whereas the threading macros will create a lot of temporary copies of the data (I don't know if that's a universal truth). That is, if you're processing a 1000 items, say `gather` returns a 1000 items, that 1000 item list is passed to `uppercase-list` which return a new 1000 item list to feed to `sort` which returns another 1000 item list (assuming none of these are destructive).

I wish CL had something like the Java streams (maybe it does).

harryposner 2 hours ago | parent | next [-]

Clojure has two options:

The version with a threading macro, will create a lazy-sequence for each step in the pipeline. It will not instantiate the entire list, so it's O(1) memory overhead in terms of peak memory, but it churns O(N) extra garbage.

    (->> things
         (map model/find-thing)
         (filter some?))
And the version with transducers, which will not create any intermediate sequences:

    (sequence (comp (map model/find-thing)
                    (filter some?))
              things)
It looks like there's a Common Lisp transducers library, but I have no idea how widely it's used.

https://github.com/fosskers/transducers

kagevf 2 hours ago | parent | prev | next [-]

Apparently, the Series library offers that. It didn't make it into the ANSI standard, but it's still maintained and covered in CLtL2.

edit SICP has examples on how to implement streaming (in Scheme).

evdubs 3 hours ago | parent | prev [-]

I am pretty sure Racket's `stream` will handle this use case.

https://docs.racket-lang.org/reference/streams.html

matheusmoreira 2 hours ago | parent | prev [-]

Love those.