SRFI 197: Threading Macros Arthur A. Gleckler (09 Jun 2020 03:41 UTC)
First comments Marc Nieper-Wißkirchen (09 Jun 2020 06:48 UTC)
Re: First comments Linus Björnstam (09 Jun 2020 07:27 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 08:30 UTC)
Re: First comments Adam Nelson (09 Jun 2020 13:25 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 14:06 UTC)
Re: First comments Lassi Kortela (09 Jun 2020 14:12 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 15:28 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 16:05 UTC)
Re: First comments Adam Nelson (09 Jun 2020 16:15 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 16:22 UTC)
Re: First comments Arne Babenhauserheide (09 Jun 2020 17:03 UTC)
Re: First comments Adam Nelson (09 Jun 2020 17:16 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 17:22 UTC)
Re: First comments Lassi Kortela (09 Jun 2020 17:31 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 17:40 UTC)
Re: First comments Arne Babenhauserheide (09 Jun 2020 22:19 UTC)
Re: First comments Marc Nieper-Wißkirchen (10 Jun 2020 06:16 UTC)
Re: First comments Linus Björnstam (10 Jun 2020 07:17 UTC)
Re: First comments Marc Nieper-Wißkirchen (10 Jun 2020 07:38 UTC)
Re: First comments Linus Björnstam (10 Jun 2020 08:21 UTC)
Re: First comments Marc Nieper-Wißkirchen (10 Jun 2020 08:42 UTC)
Re: First comments Linus Björnstam (15 Jun 2020 19:50 UTC)
Re: First comments Marc Nieper-Wißkirchen (15 Jun 2020 20:09 UTC)
Re: First comments Linus Björnstam (16 Jun 2020 11:39 UTC)
Re: First comments Arne Babenhauserheide (10 Jun 2020 07:53 UTC)
Re: First comments Marc Nieper-Wißkirchen (10 Jun 2020 08:04 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 17:44 UTC)
Re: First comments Adam Nelson (09 Jun 2020 17:46 UTC)
Re: First comments Marc Nieper-Wißkirchen (09 Jun 2020 17:49 UTC)
Re: First comments Arvydas Silanskas (09 Jun 2020 07:40 UTC)
Named procedure; RE: SRFI 197: Threading Macros Arne Babenhauserheide (09 Jun 2020 13:40 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Adam Nelson (09 Jun 2020 13:48 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 14:09 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros hga@xxxxxx (09 Jun 2020 14:16 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Lassi Kortela (09 Jun 2020 14:42 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 14:48 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros hga@xxxxxx (09 Jun 2020 15:10 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 15:25 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Arne Babenhauserheide (09 Jun 2020 15:47 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 15:58 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Adam Nelson (09 Jun 2020 16:21 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 16:46 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Adam Nelson (09 Jun 2020 17:13 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 17:35 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros John Cowan (11 Jun 2020 00:59 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros hga@xxxxxx (09 Jun 2020 16:58 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Lassi Kortela (09 Jun 2020 17:00 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Arne Babenhauserheide (09 Jun 2020 17:00 UTC)
Re: Named procedure; RE: SRFI 197: Threading Macros Marc Nieper-Wißkirchen (09 Jun 2020 15:17 UTC)
Usecase: chaining operations after "optionals" Arne Babenhauserheide (09 Jun 2020 17:18 UTC)
Re: Usecase: chaining operations after "optionals" Adam Nelson (09 Jun 2020 17:24 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (09 Jun 2020 17:48 UTC)
Re: Usecase: chaining operations after "optionals" Adam Nelson (09 Jun 2020 17:55 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (09 Jun 2020 19:11 UTC)
Re: Usecase: chaining operations after "optionals" Arne Babenhauserheide (09 Jun 2020 22:08 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (10 Jun 2020 06:11 UTC)
Re: Usecase: chaining operations after "optionals" Arne Babenhauserheide (10 Jun 2020 08:03 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (10 Jun 2020 08:10 UTC)
Association list utilities Lassi Kortela (10 Jun 2020 08:24 UTC)
Re: Association list utilities Marc Nieper-Wißkirchen (10 Jun 2020 08:30 UTC)
Re: Association list utilities Lassi Kortela (10 Jun 2020 08:49 UTC)
Re: Association list utilities Marc Nieper-Wißkirchen (10 Jun 2020 09:29 UTC)
Re: Association list utilities Lassi Kortela (10 Jun 2020 09:59 UTC)
Re: Association list utilities Marc Nieper-Wißkirchen (10 Jun 2020 10:09 UTC)
Re: Association list utilities Lassi Kortela (10 Jun 2020 10:37 UTC)
Re: Association list utilities Arne Babenhauserheide (10 Jun 2020 10:33 UTC)
Re: Usecase: chaining operations after "optionals" Arne Babenhauserheide (10 Jun 2020 09:16 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (10 Jun 2020 09:19 UTC)
Re: Usecase: chaining operations after "optionals" Lassi Kortela (10 Jun 2020 09:29 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (10 Jun 2020 09:42 UTC)
More on association lists (and other key-value collections) Lassi Kortela (10 Jun 2020 10:16 UTC)
Re: More on association lists (and other key-value collections) Marc Nieper-Wißkirchen (10 Jun 2020 10:42 UTC)
Re: More on association lists (and other key-value collections) Arne Babenhauserheide (11 Jun 2020 00:41 UTC)
Re: More on association lists (and other key-value collections) Marc Nieper-Wißkirchen (11 Jun 2020 10:07 UTC)
Re: Usecase: chaining operations after "optionals" Arne Babenhauserheide (10 Jun 2020 10:28 UTC)
Re: Usecase: chaining operations after "optionals" Marc Nieper-Wißkirchen (10 Jun 2020 10:32 UTC)

Re: First comments Adam Nelson 09 Jun 2020 13:25 UTC

On 6/9/20 2:48 AM, Marc Nieper-Wißkirchen wrote:

> Dear Adam,
>
> congratulations to your first SRFI!

Thanks!

> (1) In the issue section, you wrote that the name "threading macros"
> may be a bit misleading, and, in fact, when I read the SRFI's title in
> Arthur's announcement, I thought it had something to do with threads.
>
> What about a name that uses the word "sequencing" like in "sequencing
> operators" instead?

That's a possibility. I'm also considering "pipeline operators".

> (2) The fact that the macros `->' and `->>' do some automatic wrapping
> in parentheses leads to some inconsistencies, so I would drop it. At
> the moment, the macros rely too much on the syntax:
>
> (-> x f)
>
> result in `(f x)'. If `f' is itself the result of a call to the thunk
> `g' (or the expansion of a macro named `g'), the user will expect that
>
> (-> x (g))
>
> does the same. It doesn't, however, because this expands into `(g x)'.
This is a difficult one to accept, because it takes away from the
terseness of these macros, which was their original purpose... and it is
also a significant departure from the original Clojure syntax. I can see
the point about consistency though, and Scheme in general seems to
prefer consistency over terseness. I'll consider it.
> (3) The description of `as->' is harder to understand than reading its
> definition in terms of the syntax-rules macro. The macro allows many
> more uses than what the description says.
How would you suggest rephrasing it? (Then again, it might not be in the
next draft, depending on which suggestions I take.)
> (4) Reading the descriptions of `some->' and `some->>', I am wondering
> whether the whole syntax of this SRFI can be merged with the syntax of
> SRFI 2, reducing the number of overlapping syntaxes. SRFI 197 seems to
> (partially) describe `and-let*' constructs where the intermediate
> variables can be made anonymous.
There is certainly overlap between `some->` and `and-let*`. I'd consider
renaming it to `and->`, since the original `some->` in Clojure
short-circuited on Java null, not on false. I wouldn't want to merge
`some->` and `->` though; there's still a use case for the
non-short-circuiting operator.
> (5) As `cond->' and `cond->>' do not short-circuit, `when->' and
> `when->>' maybe better names.
Agreed, I'll make that change in the next draft.
> (6) These macros do not handle procedures returning multiple values;
> this may not be an issue with Clojure (I don't know), but it should be
> taken into consideration with Scheme. Especially for pipelining,
> multiple values can come in handy when more than one value has to be
> threaded through (or just at some intermediate stages).
I agree that this should be default functionality; if a procedure
returns two values, it should expand into two arguments at the front or
back of the next call in the pipeline. I am concerned about the
performance impact of this in the default case, though. Schemes without
sophisticated compilers will be slowed down by making each pipeline call
a `call-with-values` followed by an `apply` with list concatenation.
> (7) The draft uses the term "function" several times, where it would
> be called "procedure" in the Scheme world.
Good catch, I'll fix that in the next draft.
> (8) It took me a moment to understand what you meant by "thread-first"
> and "thread->last". I don't find the difference in the symbols `->'
> and `->>' self-explanatory in this regard.
This is the language used in the Clojure world, but I agree that it's
not especially clear. I should at least describe them better, without
using those terms. Hypothetically, `->>` could be renamed to `last->`,
but then there is the problem of symbols like `some->>` -- is it now
`some-last->`? `some/last->`?
> (9) `as->' needs a dummy argument `name', which is not needed from a
> language-designers point of view. I would suggest getting rid of it
> and having SRFI 197 export an identifier that is used to mark the
> slot. This can be implemented as `yield' in SRFI 190.

I don't want to get syntax parameters involved in this SRFI if I can
help it. The original Clojure threading macros are extremely simple and
can be implemented in 3 lines of `syntax-rules`; in theory, they can be
implemented in any Scheme without requiring any changes. Requiring
syntax parameters would be an obstacle to adoption. With that said...

On 6/9/20 4:29 AM, Marc Nieper-Wißkirchen wrote:
> If this means that we can get rid of the dichotomy between `->' and
> `->>' all the better (as they only handle special cases anyway). So
> you think of something like this?
>
> (-> x (f <> 1) (+ 2 <> 4))
>
> If we go this route, the macro arguments of `->' can all be
> expressions and do not have to be procedure calls, widening the
> applicability of the `->' syntax. In that case, however, you don't
> want to scan for `<>' recursively in the argument expressions (this
> won't understand lexical scoping), but you would make `<>' a syntax
> parameter bound to identifier syntax (as yield in SRFI 190). This is
> easily implementable in Guile and would just work.

I like parts of this suggestion. Using `<>` and `<...>` from `cut` is a
good idea, but I'd still like to avoid syntax parameters. I think it
would make more sense to mimic the syntax of `cut` and only allow `<>`
or `<...>` at the top level.

Here's what I'm thinking for the next draft:

- Unify `->`/`->>` and `as->` using the `cut` syntax. `->` and `->>`
still exist, and have the same behavior when `<>` is missing, but `<>`
can be used to move the argument somewhere else.

- Use multiple `<>` (as in `cut`) for multiple arguments; when these are
present, it is assumed that the previous entry in the pipeline will
return the same number of values.

- `<...>` expands a list returned by the previous pipeline entry as
multiple arguments.

- Actually, it's probably a good idea to keep `as->` around, because it
allows referencing the last pipeline entry's return value in multiple
places.

> However, I would then unify the syntax with the existing constructs of
> Scheme to simply and regularize things:
>
> (-> x (f <> 1) (+ 2 <> 4))
>
> would become
>
> (let* ((x) ((f <> 1))) (+ 2 <> 4))
>
> In other words, we simply extend the let* syntax as it is done with
> and-let* in SRFI 2 by allowing binding clauses to be a list of length
> 1. In these cases, the result is bound to an implicit identifier,
> which is then bound to `<>' in subsequent steps.
>
> Replacing `let*' by `and-let*' would implement the `some->' semantics.

While I appreciate the ingenuity, this seems much less clear than the
arrow macros. The arrow syntax will at least be familiar to anyone who
is aware of Clojure, whereas this new syntax overloads `let*` with a new
(albeit similar) meaning. The `let*` syntax also involves two more
levels of parentheses (once again reducing terseness), and requires
either extending or overriding a built-in form, creating another
obstacle to adoption.

- Adam