empty intervals
Alex Shinn
(21 Apr 2022 11:02 UTC)
|
Re: empty intervals
Bradley Lucier
(21 Apr 2022 16:30 UTC)
|
Re: empty intervals
Bradley Lucier
(21 Apr 2022 16:37 UTC)
|
Re: empty intervals
Per Bothner
(21 Apr 2022 19:23 UTC)
|
Re: empty intervals Bradley Lucier (21 Apr 2022 21:59 UTC)
|
Re: empty intervals
Per Bothner
(21 Apr 2022 22:11 UTC)
|
Re: empty intervals
Bradley Lucier
(23 Apr 2022 17:56 UTC)
|
Re: empty intervals
Per Bothner
(23 Apr 2022 19:44 UTC)
|
Re: empty intervals
Alex Shinn
(24 Apr 2022 05:03 UTC)
|
Re: empty intervals
John Cowan
(21 Apr 2022 22:56 UTC)
|
Re: empty intervals
Alex Shinn
(22 Apr 2022 09:03 UTC)
|
Per: I looked again a bit at SRFI 164. Thanks for reminding me of it. This SRFI has a routine make-specialized-array-from-data, which allows one to treat some one-dimensional objects (vectors and homogeneous vectors) as arrays. (This reminds me that right now we do not have a string-storage-class, or perhaps this would be better names as character-storage-class, because my limited understanding is that a string is not always simply a concatenated list of characters.) If this SRFI were to be extended to incorporate zero-dimensional arrays or arrays with length zero axes, then each routine would need to be carefully examined to determine what the semantics would be on these "new" objects. Or at least that is what I, personally, would require. The rest of this email tries to go through such a thought process with the array-squeeze example I gave above. The first part is pretty coherent, then later it loses focus. In my thoughts on the matter, zero-dimensional arrays that contain a single element, a box, as you say, makes more sense to me than arrays that have zero-length axes. To be honest, I cannot see how SRFI 164 deals with array-ref with arrays some of whose axes have length zero. The following discussion speculates about what array-curry should do in such special cases. Brad So, for example, the general case of the array-squeeze I gave above has the formula (*): (car (array->list (array-curry ;; this array has only one element. (array-permute a permutation) (- dim (length ks))))))))) where ks is the list of axes of a of length 1, permutation is a permutation that reorders the list of axes to place length-one axes first. The two special cases are when all axes have length 1, or when no axes have length 1, in which cases the second argument to array-curry has values 0 and dimension of a, respectively, both cases that are not currently allowed. If we were to allow (*) to work when no axes have length 1, then (array-curry a (array-dimension a)) should return an array of dimension 0, which contains the original array a, and array->list applied to that zero-dimensional array should return a length-one list containing a, and the car of that list will be a. If we were to allow (*) to work when all axes have length 1 (so a has a single element), then (array-curry a 0) should return an array with that single element; the dimension doesn't matter if all we're going to do with the result is (car (array->list (array-curry a 0))) So should (array-curry a 0) return a itself for all a, even those with more than one element? This would make (*) work. Actually, for array-curry, this might not be a terrible idea so far: (a) (array-curry a (array-dimension a)) => zero-dimension array containing a (b) (array-curry a 0) => a Or because (array-curry A k) returns an array whose elements are arrays. should (array-curry a 0) return a new array where every element of a is wrapped in a new zero-dimensional array? Which properties are we going to insist are consistent? Now let's start thinking about arrays with domains that are zero-length in some dimension. So at least one direction k of the domain will not have length 1, so the (array-curry a 0) case (b) will be avoided. If none of the axes has length 1 then case (a) will be invoked, so again array-curry will return a zero-dimensional array containing a, array->list will return a one-element list with a as the only element, and car will return the original array. Seems to make sense. Let's assume now that at least one axis of a has length 1. Then those axes will be reordered to be at the front, array-curry will return a usual-type array all of whose axes will have dimension 1, the single element of which will be an array with at least one axis length 0. Again, seems to make some sense, in that it seems self-consistent so far. ==================================== Now I think: what if we move all the length-zero axes to the front, instead of the length-one axes to the front, and then call array-curry on the resulting array. In other words, what does (array-curry a (- (array-dimension a) 1)) return if the first dimension has length zero? If you follow the general formula, it should return a length 0 array, each element of which is an array with domain consisting of the remaining axes in order. A length-zero array has no elements. It would seem that a length-zero array should have a getter that just raises an error. So (define B (array-curry (make-array (make-interval '#(0 1))) 1)) should return an array that (array-ref B i) => error and (define B (array-curry (make-array (make-interval '#(1 0))) 1)) returns an array such that (array-ref B 0) => an empty array and (array-ref (array-ref B 0) i) => error It seems to be a question of at which point the error is raised in the curried result. ================================= And now, if functionally an array with at least one axis of length zero has (array-ref a i j k l) raise an error no matter the number or values of the arguments, is there a difference between empty arrays of different dimensions?