relationship to SRFI-25
Per Bothner
(30 Jul 2015 05:30 UTC)
|
Re: relationship to SRFI-25
John Cowan
(30 Jul 2015 20:20 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(31 Jul 2015 21:00 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(26 Sep 2015 18:33 UTC)
|
Re: relationship to SRFI-25
Per Bothner
(27 Sep 2015 05:34 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(28 Sep 2015 21:04 UTC)
|
Re: relationship to SRFI-25
Per Bothner
(28 Sep 2015 21:29 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(28 Sep 2015 21:54 UTC)
|
Re: relationship to SRFI-25
Jamison Hope
(28 Sep 2015 22:22 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(28 Sep 2015 22:38 UTC)
|
Re: relationship to SRFI-25
Jamison Hope
(28 Sep 2015 23:20 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(29 Sep 2015 06:03 UTC)
|
Re: relationship to SRFI-25 Jamison Hope (29 Sep 2015 16:12 UTC)
|
Re: relationship to SRFI-25
Bradley Lucier
(30 Sep 2015 03:42 UTC)
|
On Sep 29, 2015, at 2:03 AM, Bradley Lucier <xxxxxx@math.purdue.edu> wrote: > On 09/28/2015 07:20 PM, Jamison Hope wrote: > 't really understand this part. >> >> I'm not suggesting that array-map be implemented on top of array-ref, >> or that whatever other mutating functions there are be implemented >> on top of array-set! -- just that as an end user, having to extract >> and then invoke a closure rather than just calling a setter or getter >> *function* seems strange. > > OK. > > Often, there is only the getter function. (I'm not sure what > distinction you're trying to make when you call it a "closure".) The getter and setter functions do not take the array object or any related context as an argument, only the indices. If a cell's value is purely a function of its location (as in an identity matrix), then the array must be immutable and the getter will be a function. But in every other case, the getter function and (optional) setter must close over some direct or indirect storage in order to do the appropriate lookup/assignment. They are closures. There's nothing wrong with that per se, but it's a lot more.. object-oriented (a la Smalltalk, not CLOS) than most Scheme/Lisp APIs. (This reminds me of Anton's koan about Master Qc Na [1].) Suppose I want to write my own mutable array implementation backed by vectors (I know there are API-supplied functions for this, but humor me). In my case, I only care about 2D 3x3 matrices because I intend to use them to represent spatial rotations or something like that. At the lowest level, I need these two functions: (define (matrix3-ref v i j) (vector-ref v (+ (* i 3) j))) (define (matrix3-set! v newval i j) (vector-set! v (+ (* i 3) j) newval)) But they aren't directly usable as SRFI-122 getter and setter functions, because the latter must close over the storage v. For each matrix instance I will need to allocate three objects (not including the SRFI-122 array object and its interval object): the vector where the data will live, and two lambdas that wrap calls to matrix3-ref and matrix3-set!: (let ((v (make-vector (* 3 3) 0))) ;; first object (mutable-array (interval '#(0 0) '#(3 3)) (lambda (i j) (matrix3-ref v i j)) ;; second object (lambda (val i j) (matrix3-set! v val i j)))) ;; third object As an alternative, suppose the API for mutable-array looked like this: (mutable-array domain getter setter context) where context is of arbitrary type but the getter and setter functions are specified to take the context as an argument (they are free to ignore it if they wish): (getter context i_1 ... i_n) and (setter context val i_1 ... i_n). With this hypothetical API, I could construct my 3x3 mutable array with this: (mutable-array (interval '#(0 0) '#(3 3)) matrix3-ref matrix3-set! (make-vector (* 3 3) 0)) The only allocations now are the interval, the vector, and the mutable-array. Then we would need an additional function (array-context array), and a "get" call would look like ((array-getter a) (array-context a) i j) But I digress. My original point was just that with most Scheme APIs, the user-level single-element accessors are functions TYPE-ref and TYPE-set! which take as arguments an instance of the TYPE as well as the location within TYPE (index or key). If I want to read out single values from several vectors, I repeatedly call the same function (vector-ref) passing each vector in turn. If I want to read out single values from several strings, I repeatedly call the same function (string-ref) passing each string in turn. If I want to read out single values from several SRFI-25 arrays, I repeatedly call the same function (array-ref) passing each. If I want to read out single values from several SRFI-122 arrays, I must explicitly retrieve a separate getter procedure for each array. Again, there's nothing wrong with that in principle, but within the ecosystem of existing Scheme libraries, it violates the principle of least astonishment. -Jamie [1] https://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html -- Jamison Hope xxxxxx@alum.mit.edu