|
Review of SRFI 122 draft #8
John Cowan
(23 Aug 2016 20:50 UTC)
|
|
Re: Review of SRFI 122 draft #8 Bradley Lucier (24 Aug 2016 21:40 UTC)
|
|
Re: Review of SRFI 122 draft #8
John Cowan
(24 Aug 2016 22:43 UTC)
|
|
Re: Review of SRFI 122 draft #8
Bradley Lucier
(25 Aug 2016 23:07 UTC)
|
|
Re: Review of SRFI 122 draft #8
John Cowan
(26 Aug 2016 01:51 UTC)
|
|
Re: Review of SRFI 122 draft #8
Bradley Lucier
(26 Aug 2016 14:49 UTC)
|
On 08/23/2016 04:50 PM, John Cowan wrote:
> I did a full review of draft #7, but before I could post it, draft #8
> came out, which is much easier to understand,
Which is some progress, I suppose.
I'll make comments on some things, and will think about others.
> 1) In the "Other Examples" section, the lengthy outputs should be folded
> by hand across reasonable line boundaries. When I try to print the SRFI
> using Chrome, it forces everything to be displayed by using a small and
> hard-to-read font size. I ended up removing the section before
> printing, which means I have not reviewed it.
I made some changes to an internal draft at
https://github.com/gambiteer/srfi-122/
I haven't generated a pull request yet for the main repository.
>
> 2) I think the default value should be provided when a specialized array
> is created, not when a storage class is created. In addition, the maker
> function of a storage class should be callable with a single argument,
> in which case the function may return a body full of uninitialized
> garbage. This is not useful for generalized arrays, but may save time
> for specialized arrays whose initial values are uninteresting.
I agree that it may save some time, but I believe that returning
uninitialized garbage is generally frowned upon for various reasons,
including security reasons.
>
> 3) The SRFI should say that generic-storage-class behaves *as if* the
> specified definition were used. This allows faster versions of
> vector-ref, vector-set!, etc. to be used.
Fixed in internal draft.
>
> 4) In the following paragraph, "generic-storage-class" is not in code font.
Fixed in internal draft.
> 5) It should be explicitly stated that arrays, specialized arrays, and
> intervals are disjoint types.
I'm not going to argue against this, but let me ask "why?" Translations
and permutations are not disjoint types. And a specialized-array is an
array, so in what way are these types disjoint?
> 6) The section on specialized arrays is labeled "Global Variable"
> instead of "Specialized Arrays".
Fixed in internal draft.
> 7) It is implied that specialized-array-default-safe? can be mutated.
> Neither R6RS nor R7RS permits the mutation of exported variables. A
> SRFI 39 parameter would work, or you could just remove this
> functionality and require people to pass #t to `specialized-array` if
> they want a (doubly) safe array.
I introduced two procedures, specialized-array-default-safe? and
specialized-array-default-safe?-set!
>
> 8) You should make clear what the effects are of mutating the vectors
> passed to `interval` and returned by `interval-upper-bounds` and
> `interval-lower-bounds`. I recommend that it be an error, which means
> none of these operations needs to copy the vectors.
In the reference implementation there is no effect on mutating the
arguments to interval or the results of interval-upper-bounds->vector or
interval-lower-bounds->vector. I prefer to keep it this way.
So, do you think I still need to explain something?
>
> 9) The definitions of getters and setters are backward compatible with
> Common Lisp and other SRFIs, but make for implementation
> inefficiencies. When a multi-index exists only as a sequence of
> arguments to a procedure, Scheme requires that the implementation of
> procedure calls reify the arguments as a list before being passed to the
> called procedure,
I don't know what you mean. The (heavily-macrofied) C code generated by
Gambit for (setter 1 0 0) in
(define (test)
(let ((getter (array-getter A))
(setter (array-setter A)))
(setter 1 0 0)
(getter 0 0)))
is
___SET_R3(___FIX(0L))
___SET_R2(___FIX(0L))
___SET_STK(-5,___R1)
___SET_R1(___FIX(1L))
___SET_R0(___LBL(4))
___JUMPGENNOTSAFE(___SET_NARGS(3),___STK(-5))
The three arguments are stored in registers R1, R2, and R3, the return
address is stored in R0, and there's a direct jump to the label for the
code for getter, which has been put into ___STK(-5). I don't see any lists.
> and this has to be done *every* time the procedure is
> called.
>
> If you instead require the caller to reify it as a vector and pass the
> vector, it can be reified just once and mutated on successive calls.
> Admittedly, this is somewhat less convenient, but if you want
> convenience more than performance, (getter (vector 1 2 3)) is only
> slightly more verbose than (getter 1 2 3), and may indeed allocate less
> storage.
>
> Using this approach for setters allows the new value to be the last
> argument rather than the first, in conformity with setters for other
> data types. It likewise means that the mapping procedure passed to
> `specialized-array-share` simply accepts a vector and returns a vector,
> rather than messing with variable arguments and multiple values.
>
> 11) Here are some procedures you might want to consider adding:
>
> Constructor: array-tabulate (populates the array with successive calls
> to a tabulation function with argument 0, 1, 2, ...)
One could do
(define (array-tabulate f domain #!optional (storage-class
generic-storage-class) (safe? (specialized-array-default-safe?))
(array->specialized-array
(make-array domain
(let ((i 0))
(lambda args
(let ((result (f i)))
(set! i (+ i 1))
result))))
storage-class
safe?))
array->specialized-array does a lot of error checking, I'd like to avoid
repeating that code in other procedures.
>
> Array-ref and array-set! convenience methods for getting and setting
> without explicitly retrieving the getter/setter.
I'm trying to offer alternatives to word-at-a-time array processing in
this SRFI.
>
> Whole-array functions: array-fold (fold in lexicographic order),
> array-reduce, array-scan (APL), array-count, array-index. All of these
> are basically equivalent to converting the array to a list and operating
> on the list, but much more space and time efficient.
I don't know what these do: array-scan, array-count, array-index.
I have array-reduce; how does it differ from array-fold?
>
> Additional simple transformation on all arrays: array-diagonal (returns
> a 1d array containing the diagonal elements up to the smallest dimension)
>
> Others: array-append (along a specified dimension), array-repeat
> (append to itself N times along a specified dimension),
> nested-list->specialized-array (needs number of dimensions),
> nested-vector->specialized-array, array->nested-list,
> array->nested-vector, inner product (two procs), outer product (one proc).
Perhaps these are best to leave to another SRFI. (I have used
array-append in my own codes.)