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)
|
> The point is that values->list (or receive-list or however we are > going to name it) has to be syntax (e.g. implemented as a macro) > because of the limitations of Schemes applicative syntax. Sorry, I was sloppy with terminology. While (values->list (foo)) is indeed syntax, it's very lightweight and looks like an ordinary procedure call. (receive (a b c) (foo) body...) looks very different because the body is included. > "multiple values" are no first-class concept (unless you reify > them with multiple value boxes). A procedure named `foo->bar` should > transform objects of type `foo` into objects of type `bar`. This > reading does not work if `bar` is replaced by the word `values`. Very good point. Maybe that kind of pun is not clean enough :) One of Scheme's best aspects is the consistent attention to detail. > Maybe, replacing "->" by "-" helps here. So `list-values` and > `vector-values`. The trouble with using only a hyphen is that it's not obvious which way the conversion is done. Common Lisp's `values-list` turns a list into multiple values, but its name sounds like it would do the opposite. The opposite operator, `multiple-value-list`, sounds like an alias instead of an opposite. It could be named `values-from-list`, and there could be a matching `list-from-values`. But that's arguably just a clever way of writing `list-to-values` and `values-to-list` in reverse. And `-to-` sounds like a synonym of `->` so it would be confusing to add such names to Scheme. In that sense `receive-list` would be more obvious. But `receive` doesn't have an established antonym in this context. IMHO `send` sounds too fancy and is easy to confuse with concurrency or networking stuff. `let` has the same problem (?) as `receive` in that people may expect it to have a body. The word `bind` (as used by Common Lisp) is reasonable, but CL's `multiple-value-bind` also has a body. >>> Racket has `set!-values` >>> 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? > > Yes. And there should be a reference to SRFI 17 for Schemes that > implement it. (NB: But we should remember that there are also reasons > for not promoting the idea of SRFI 17: > https://srfi-email.schemers.org/srfi-17/msg/2778583/) Good idea. >> 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. > > We should see whether this protocol can be implemented efficiently. > However, I don't think that the number of values passed in each > iteration step should be forced to be fixed. The next iteration should > receive as many values as the previous one produced. (BTW, this > requirement rules out my simplest syntax proposal.) That would require something like a `case-lambda` for the step procedure. Would there be any practical problem that is most productively solved in this way? Multiple-value boxes offer an obvious way to pass a different number of values at each step, though not sure about the efficiency. >> 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. > > So you mean that the iteration/recursion procedure has to unbox the > seed by hand and the multiple values it returns will be auto-boxed for > the next iteration by `fold*`? Yes, exactly. Again, this is probably not that efficient :) > I will add a system-specific implementation (for Chibi) to show how to > implement them efficiently when the system already packages multiple > values into some internal structure. Great. >>> 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?). > > The problem I have just seen here is that <seed-formals> is fixed in > size, forcing the same number of values passed in each step (which is > a bit of an unnatural requirement). >>> 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)? > > The syntax may be simplified. Boxing, however, adds another level of > indirection, so boxing both seeds and lists may be a bit too much. It's not clear how to avoid indirection. An inner lambda adds indirection as well. Perhaps inner lambdas are easier to eliminate by existing Scheme inliners. >> We should probably have that one in any case. >> >> (fold* (lambda (elem acc1 acc2) ... (values new-acc1 new-acc2)) >> list init1 init2) > > Indeed; this will be used often and should be simple. For hash-tables, > this is all we would need (it does not make sense to process unordered > lists in parallel). Good point. > In order to keep the dependencies of this planned SRFI below a certain > limit, I would propose that procedures like > > hash-table-fold*, generator-fold*, stream-fold*, ifold*, ... > > go into their respective SRFI libraries (taking the same approach as > SRFI 162, which amended the SRFI 128 library) once we have agreed on > the signature. Sounds reasonable. > We also want to talk about `unfold*` and friends. For example, there > is currently no idiomatic way to create a SRFI 125 hash table from a > list of keys and a list of values (values not in the mv sense :)). > While `alist->hash-table` can be defined through `hash-table-unfold`, > this doesn't work with separate lists of keys and values because > `hash-table-unfold` is restricted to a single seed. Something like the following? (define (lists->hash-table ks vs) (unfold* (values ks vs) (lambda (ks vs) (and (pair? ks) (pair? vs))) (lambda (ks vs) (values (cdr ks) (cdr vs))) (make-hash-table) (lambda (hash-table k v) (hash-table-set! hash-table k v) hash-table)))