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 Marc Nieper-Wißkirchen 09 Jun 2020 14:05 UTC

Am Di., 9. Juni 2020 um 15:25 Uhr schrieb Adam Nelson <xxxxxx@nels.onl>:
>
> On 6/9/20 2:48 AM, Marc Nieper-Wißkirchen wrote:

> > What about a name that uses the word "sequencing" like in "sequencing
> > operators" instead?
>
> That's a possibility. I'm also considering "pipeline operators".

Pipelining is a term that I haven't seen before in the Scheme world.
"Sequencing", however, quite often. And what the macro does is really
sequencing because it forces an evaluation order.

> > (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.

Scheme is neither Clojure, not Common Lisp, nor JavaScript.  So some
(significant) departure does not need to be a bad sign, quite to the
contrary.

It's just one more pair of parentheses, so not much of the terseness
is being lost. Moreover, if you look for terseness, Scheme is not a
good example. That said, this is possibly a good thing.

In any case, that macros work flawlessly and transparently is
certainly more important. If the original Clojure macro exhibits the
same problem, already the original macro is broken and we shouldn't
copy it, but correct it.

> How would you suggest rephrasing it? (Then again, it might not be in the
> next draft, depending on which suggestions I take.)

Let's postpone this until we know what the final shape is.

> > (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

`and->' sounds better than `some->'.

> > (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

It's not completely clear to me why the positions at the front or at
the back are singled out as Scheme is not a language with automatic
currying where the actual positions of parameters have more meaning.
That's why the placeholder idea (the "<>") seems to make more sense.

> 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.

Scheme has an impoverished API for multiple values. I hope to get out
a SRFI with more fundamental mv procedures, which can be implemented
efficiently, soon so that SRFI 197 could hopefully then implemented
efficiently in terms of the fundamental mv syntax.

> > (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->`?

As already said by other people, the whole symbol business "->"
instead of a proper name (maybe decorated) is not very Schemy.

> > (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...

With a syntax parameter, the implementation may need 7 lines but 3,
but on the side of the macro user (and from a language-designers point
of view), things become simpler. And you only need to write a macro
once, but a good macro will be used a thousand times.

> 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.

That's a strange and needless (apart from implementation constraints)
restrictions. Why should procedure calls be special? What you make if
someone puts a binding construct as a top-level form and your scanning
macro misinterprets this as a procedure call. No, the only clear way
to solve this, has to use syntax parameters (or, possibly, some
unhygienic low-level hackery).

Just vote for the inclusion of SRFI 139 into R7RS-large and don't
worry about adoption. And implement syntax parameters for your
favorite Scheme dialect that doesn't yet have them! :)

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

> - 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.

You would want to be able to permute the order. There is no reason why
the values come in the same order as are the arguments of the
following procedure.

> > 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

It doesn't overload `let'' with a "similar" meaning, I'd say. I mean,
`let'' has always been the Scheme equivalent to `->' (and that's
probably why Scheme could have lived without `->' so far :)). The only
difference is that Clojure's `->' allows anonymous intermediate
results (for good and for bad). What I have been proposing is just the
canonical extension of `let'' to allow such anonymous intermediate
results as well. Familiarity with `let'' may count more than
familiarity with Clojure.

> levels of parentheses (once again reducing terseness), and requires
> either extending or overriding a built-in form, creating another
> obstacle to adoption.

It's a 5-minute job to add this to every single implementation. This
doesn't make it an automatic addition, but if the macro is good and
usable, why not?

Apart from that, there have been proposals for an export form for
Scheme libraries that actually allows overriding bindings, so that
(import (scheme base)) (import (srfi 197)) could work even if SRFI 197
exported its own `let''.