|
Introspection
Wolfgang Corcoran-Mathe
(10 May 2020 23:41 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(11 May 2020 07:11 UTC)
|
|
Multiple-values SRFI Lassi Kortela (11 May 2020 09:09 UTC)
|
|
Re: Multiple-values SRFI
Marc Nieper-Wißkirchen
(11 May 2020 09:41 UTC)
|
|
Re: Multiple-values SRFI
Lassi Kortela
(11 May 2020 10:52 UTC)
|
|
Re: Multiple-values SRFI
Lassi Kortela
(11 May 2020 11:04 UTC)
|
|
Re: Introspection
John Cowan
(11 May 2020 18:02 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(11 May 2020 18:26 UTC)
|
|
Re: Introspection
Marc Feeley
(11 May 2020 18:34 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(11 May 2020 19:29 UTC)
|
|
Re: Introspection
Marc Feeley
(12 May 2020 04:15 UTC)
|
|
Re: Introspection
John Cowan
(12 May 2020 15:36 UTC)
|
|
Re: Introspection
Lassi Kortela
(12 May 2020 16:07 UTC)
|
|
Re: Introspection
John Cowan
(12 May 2020 18:19 UTC)
|
|
Re: Introspection
Lassi Kortela
(12 May 2020 18:46 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(04 Jun 2020 16:39 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(09 Jun 2020 08:38 UTC)
|
|
Re: Introspection
John Cowan
(09 Jun 2020 17:53 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(09 Jun 2020 19:39 UTC)
|
|
Re: Introspection
John Cowan
(10 Jun 2020 21:46 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(11 Jun 2020 11:55 UTC)
|
|
Re: Introspection
Marc Nieper-Wißkirchen
(04 Jun 2020 16:36 UTC)
|
> I will then submit a general multiple values SRFI before SRFI 195 is
> finalized (and maybe also before SRFI 189 is). This SRFI will include
> syntax like
>
> [...]
>
>>> (values->vector <expr>)
>>> (values-length <expr>)
>>> (values->list <expr>)
>>> (values-ref <expr> <index>)
+1. Very nice API. I've wished for something like this.
FWIW, the Common Lisp multiple values API is basically everything on the
page
<http://www.lispworks.com/documentation/HyperSpec/Body/c_data_a.htm>
with "value" in its name:
Macro MULTIPLE-VALUE-BIND
Special Operator MULTIPLE-VALUE-CALL
Macro MULTIPLE-VALUE-LIST
Special Operator MULTIPLE-VALUE-PROG1
Macro MULTIPLE-VALUE-SETQ
Accessor VALUES
Function VALUES-LIST
Constant Variable MULTIPLE-VALUES-LIMIT
Macro NTH-VALUE
NOTE: In CL, values-list means list->values, not values->list.
> I am not so sure about the naming; in view of SRFI 8, it could make
> sense to use names like `receive-list`, `receive-vector`. I am open to
> suggestions!
To me, the word "receive" connotes that it's a macro (a very nice macro,
to be sure); not sure how common this association is.
"Values" is a simpler, shorter word and since the term for the concept
is "multiple values", it's probably more obvious if the operator names
talk about "values" as well.
In Common Lisp I always regretted the excessively long operator names.
"multiple-value-bind" is the simplest and most common operation; as a
newbie it was difficult to find. Scheme's "receive" and "let-values" are
a big improvement in that sense.
> Such a SRFI will also include procedures that go the other way, like
>
> (list->values <list>)
>
> which is equivalent to (apply values <list>), an often-used idiom, but
> may be implemented more efficiently.
+1, very useful!
> Again, there may be better names, like `unpack-list` or `explode-vector`.
I really like the names you chose. They are symmetrical among themselves
and with the rest of Scheme, and use common words that are familiar to
every Schemer.
> Racket has `set!-values`
> (https://docs.racket-lang.org/reference/set_.html#%28form._%28%28lib._racket%2Fprivate%2Fmore-scheme..rkt%29._set%21-values%29%29),
Nice. `define-values` is already in the standard so `set!-values` is a
natural complement. In Common Lisp, MULTIPLE-VALUE-SETQ.
> which can slightly be generalized to also take formals with a rest
> argument, and which also should go into such a multiple-values SRFI.
Even nicer. Would this be best done using the consing dot?
> Moreover, we have case-lambda that dispatches on the number of
> arguments an ordinary procedure receives; we don't have a similar
> construct for the number a continuation receives (and which could be
> useful to implement some of SRFI 189's conversion procedures whose
> protocol depends on the number of values). Therefore, I would also
> propose
>
> (case-receive <expr>
> (<formals> <body>) ...)
>
> which can be rewritten into
>
> (with-values <expr>
> (case-lambda
> ((<formals> <body>) ...)
>
> Here, `with-values` is of course
>
> (define-syntax with-values
> (syntax-rules ()
> ((with-values expr receiver) (call-with-values (lambda () expr) receiver))))
>
> (If I remember correctly, Kent Dybvig once made a point that
> `with-values` should have been standardized, not `call-with-values`
> because both are equivalent in expressiveness but it easier to work
> with an optimize `with-values`.)
LGTM.
> Another part of the language, where everyone could benefit from a
> better support of multiple values, are various higher-order
> procedures. For example, SRFI 1 defines `fold` and `fold-right`.
> `fold` is the fundamental list iteration operator and `fold-right` is
> the fundamental list recursion operator. Code that uses them is
> conceptionally clearer than code using hand-written loops with
> named-let. The problem is, however, when more than one value has to be
> threaded through the iteration or recursion.
>
> Most of the time, the user will have to go back to hand-written loops
> but will then have to deal with `values` and `let-values` explicitly.
Definitely.
> However, there is no obvious generalization of `fold` and friends to
> multiple values (which implies multiple seeds). The problem is the
> calling convention of the procedure that is being called in each step.
> Currently, it takes the accumulator and an arbitrary number of values
> corresponding to the number of lists (vectors, generators, gadgets,
> ...) being iterated or recursed over. A multiple-value version `fold*`
> would have to apply an arbitrary number of accumulator values and an
> arbitrary number of values corresponding to the number of lists
> present but there is only one rest argument.
IMHO the most obviously useful is (fold* step list init...) where N init
values mean `step` takes N accumulators and returns N values to use as
the next accumulators. At the end, `fold*` returns N values.
Using multiple-value boxes, we could also do (fold* step init list...)
where `init` is a box. `step` would then be called with M lists and N
accumulators (in either order) and return N accumulators as values.
Multiple-value boxes would work for an even more general fold* if we
pass the accumulators to `step` as boxes. This may actually be less
crazy than it sounds :)
Perhaps instead of the most generic values-fold there should be a
box-fold. In Scheme implementations with multiple-value boxes, box-fold
could take advantage of them.
M-v boxes a nice generalization that doesn't make the existing
single-value boxes any more difficult for users. If they are easy to
implement efficiently, they will hopefully be widely adopted.
> One solution would be to make `fold*` into syntax, say:
>
> (fold* (<list-formals> <seed-formals> <body>) (<seed> ...) (<list> ...)),
>
> which would work unless anyone would want to use `fold*` itself in any
> higher-order context (are there any use cases for that?).
Perhaps higher-order folds are usually done by packaging the lower-level
ones into library procedures, so the inner fold is an implementation
detail that is not visible to the outer one.
> Alternatively, `fold*` is an ordinary higher-order procedure receiving
> a procedure that evaluates into another procedure first, e.g. like the
> following or similarly:
>
> (fold* (lambda <list-formals> (lambda <seed-formals> body)) (lambda ()
> (values <seed> ...)) <list> ...)
Would it work to use m-v boxes instead (as an abstraction built
specifically for the purpose)?
> Or we could restrict `fold*` to a single list, but this would restrict
> its usefulness.
We should probably have that one in any case.
(fold* (lambda (elem acc1 acc2) ... (values new-acc1 new-acc2))
list init1 init2)
is useful and quite easy to understand.
> I would love to hear your suggestions, especially about further
> procedures and syntax that should be included.
You nicely covered all of the essentials :)