Re: Introspection Marc Nieper-Wißkirchen 04 Jun 2020 16:35 UTC

Am Di., 12. Mai 2020 um 06:15 Uhr schrieb Marc Feeley <>:

> I don’t view the “single value” nature of boxes as a restriction.  Similarly, the “two value” nature of pairs is not a restriction.  These structures correspond to specific common usage patterns:
> 1) box = mutable cell
> 2) pair = joining two values together
> Vectors are another common usage pattern where multiple elements are joined together and indexable.  Boxes and pairs are theoretically redundant because the same effect could be obtained with vectors of length 1 or 2.  When a program uses the box type it conveys to the programmer the concept that there is a single contained value.  Similarly, using the pair type conveys the concept of a group of 2 values.  This helps the programmer reason about the program better than if the vector type was used everywhere instead of boxes and pairs.

This is certainly a valid point to view boxes and pairs as special
vectors with fixed length (namely of length 1 and 2) but, as you say,
this is somewhat redundant.

Therefore, I don't adopt this point of view. I would like to leave out
pairs from the discussion because they have been there since the first
LISP, so it is about boxes and vectors. In SRFI 189, monadic sequence
operations that can be generalized to boxes and vectors. For this, one
needs in which sense a box or a vector represents a sequence. In your
point of view, the box would represent a sequence of length 1, while a
vector would represent a sequence of length n. However, as soon as I
want to store multiple values in a box and model this using a vector,
the sequence suddenly has more than length 1. On the other hand, if we
have an extra box type

The discussions in SRFI 189 and the final draft of it show that in the
monadic framework there is a subtle difference between containers
holding a number of objects or a container holding multiple values as
a sequence of length one. For example, with the boxes defined in SRFI
195, a (monadic) (box-map proc box) would call `proc' exactly once,
regardless of a single value or multiple values are boxed. On the
other hand, (vector-map proc vector) calls `proc' for each element in
the vector. This distinction cannot be upheld if boxes with multiple
values are conflated with vectors.

As I said, the other point of view is also valid but less helpful
because of the redundancy, while SRFI 195 gives something new.

Finally, `(box)' creates an object that is not `eq?' to any existing
one, while `(vector)' may result in a singleton object.

> However I like the idea of special forms to convert between multiple values and lists and vectors.  This is possible but rather verbosely with the call-with-values procedure:
>   (call-with-values (lambda () (values 1 2 3)) list)    => (1 2 3)
>   (call-with-values (lambda () (values 1 2 3)) vector)  => #(1 2 3)
> With a special form these conversions could be more direct.  Here is an idea:
>   (values=>vector (values 1 2 3))  ;; #(1 2 3)
>   (vector->values (vector 1 2 3))  ;; same as (values 1 2 3)
> Note that values=>vector is a special form and vector->values is a procedure.  There could also be list variants.
> The use of cond's => syntax reminds the reader that values=>vector is a special form and not a procedures (which typically use the -> kind of arrow like vector->values).
> An even more concise approach would limit the conversion to vectors:
>   (=>vector (values 1 2 3))  ;; #(1 2 3)
>   (->values (vector 1 2 3))  ;; same as (values 1 2 3)
> Marc