Skip to content

Instantly share code, notes, and snippets.

@pjstadig
Last active June 8, 2021 13:22
Show Gist options
  • Select an option

  • Save pjstadig/c27366b1cba7a820d07ffdc957fc86c0 to your computer and use it in GitHub Desktop.

Select an option

Save pjstadig/c27366b1cba7a820d07ffdc957fc86c0 to your computer and use it in GitHub Desktop.

Revisions

  1. pjstadig revised this gist Apr 17, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion transducers.md
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ One somewhat esoteric use of this is to transpose a matrix:
    ## The Turn
    However, transducers can only be applied to a single source...or can they?

    I noticed that `map`'s transducer takes a fourth arity with a variable number of collections. This really surprised me since as far as I could remember there were no transducing contexts that would actually work with multiple sources...or where there?
    I noticed that `map`'s transducer takes a fourth arity with a variable number of items. This really surprised me since as far as I could remember there were no transducing contexts that would actually work with multiple sources...or where there?

    I looked through `transduce`, `eduction`, `into`, and `sequence` and found that `sequnece` can take multiple collections.

  2. pjstadig revised this gist Apr 16, 2019. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion transducers.md
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,7 @@ One somewhat practical use of this is if you want to compare two sequences, pair

    ```clojure
    (every? true? (map < (range 5) (range 5 10)))
    => true
    ```

    One somewhat esoteric use of this is to transpose a matrix:
    @@ -29,7 +30,7 @@ I noticed that `map`'s transducer takes a fourth arity with a variable number of

    I looked through `transduce`, `eduction`, `into`, and `sequence` and found that `sequnece` can take multiple collections.

    Neither `map'`s fourth arity nor `sequence` taking multiple collections is mentioned in any of the transducer documentation. The only hint is `sequence`'s docstring mentions multiple collections, but you'd have look at the source for `map` to see the fourth arity.
    Neither `map`'s fourth arity nor `sequence` taking multiple collections is mentioned in any of the transducer documentation. The only hint is `sequence`'s docstring mentions multiple collections, but you'd have look at the source for `map` to see the fourth arity.

    ## The Prestige
    `map` is the only `clojure.core` transducer with a fourth arity, and `sequence` is the only `clojure.core` transducer context to supply multiple sources, so this seems to be of limited use. However, as long as `map` is the first stage of your transducer pipeline you can use other transducers with a multi-collection invocation of `sequence`:
  3. pjstadig created this gist Apr 16, 2019.
    46 changes: 46 additions & 0 deletions transducers.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    ## The Pledge
    One thing that always made me a little sad about transducers was how `map` lost its ability to iterate multiple collections in parallel. This is actually my favorite feature of `map`. For example:

    ```clojure
    (map + (range 5) (range 5 10))
    => (5 7 9 11 13)
    ```

    One somewhat practical use of this is if you want to compare two sequences, pairwise, using a comparator. Though I wish that `every?` took multiple collections, this is an adequate substitute:

    ```clojure
    (every? true? (map < (range 5) (range 5 10)))
    ```

    One somewhat esoteric use of this is to transpose a matrix:

    ```clojure
    (apply map vector [[1 2 3]
    [4 5 6]])
    => [[1 4]
    [2 5]
    [3 6]]
    ```

    ## The Turn
    However, transducers can only be applied to a single source...or can they?

    I noticed that `map`'s transducer takes a fourth arity with a variable number of collections. This really surprised me since as far as I could remember there were no transducing contexts that would actually work with multiple sources...or where there?

    I looked through `transduce`, `eduction`, `into`, and `sequence` and found that `sequnece` can take multiple collections.

    Neither `map'`s fourth arity nor `sequence` taking multiple collections is mentioned in any of the transducer documentation. The only hint is `sequence`'s docstring mentions multiple collections, but you'd have look at the source for `map` to see the fourth arity.

    ## The Prestige
    `map` is the only `clojure.core` transducer with a fourth arity, and `sequence` is the only `clojure.core` transducer context to supply multiple sources, so this seems to be of limited use. However, as long as `map` is the first stage of your transducer pipeline you can use other transducers with a multi-collection invocation of `sequence`:

    ```clojure
    (sequence (comp (map +)
    (filter even?))
    (range 5)
    (range 5 10)
    (range 10 15))
    => (18 24)
    ```

    This makes me happy!