Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail From: bart Newsgroups: comp.lang.misc Subject: Re: Algol 68 (or generally) - arbitrarily nested arrays of arrays Date: Sun, 28 Dec 2025 15:32:36 +0000 Organization: A noiseless patient Spider Lines: 118 Message-ID: <10iriik$augl$1@dont-email.me> References: <10ilrbc$25ihi$10@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Sun, 28 Dec 2025 15:32:37 +0000 (UTC) Injection-Info: dont-email.me; posting-host="101fb48439aa72802284e39de6f804a2"; logging-data="358933"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18YHwiM9q0dhuWx8QbXY/v7" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:7QsSkNzz0fa2Kz9htmcMRRxqCMs= Content-Language: en-GB In-Reply-To: <10ilrbc$25ihi$10@dont-email.me> Xref: csiph.com comp.lang.misc:11720 On 26/12/2025 11:25, Janis Papanagnou wrote: > Occasionally I had the demand to create arbitrarily nested arrays of > arrays (similar to the question in [*]). This requires something like > [][]...[] SOMETYPE and the corresponding nested loops for processing >   FOR i ... >     ... >       FOR j ... >         FOR k ... > But these are static definitions and don't scale for arbitrary depth. > (The dimension/depth of nesting is defined during runtime at start!) > > In the context of another language I had implemented such logic simply > by linearizing the arrays and the associated array index calculation. > > An alternative approach could be to build the structures recursively > (with linked data structures) and with a recursive set of functions. > > Now pondering what to do in Algol 68... > The linearization appears to be the most simple (yet effective) way. > The recursive one may be conceptually cleaner (but has more overhead). > > Or is there some code pattern [in Algol 68] that would simplify the > task without muddying the clarity of the algorithms? > > Janis > > PS: In my Algol 68 context the above written  [][]...[] SOMETYPE  is > actually rather a more coherent  [ , ,... , ] SOMETYPE  sort of array > (which makes the index-flattening simple). > > [*] https://stackoverflow.com/questions/17479241/how-to-create-a-nested- > array-of-arbitrary-depth-in-java > This looked an intriguing problem for my dynamic language. In the experiment below, such an array of considered an N-dimensional cuboid. Its size and shape is described by an N-element vector giving the bounds of each dimension (assumed to be 1-based; N must be at least 1, and no bounds are empty). The example uses a 6-dimensional array. A generic routine is used to loop over all elements, and to perform some action based on a supplied anonymous function. To allow both getting and setting of elements, this example passes a reference to the element to the supplied function, plus a vector of the indices it corresponds to. Here, the elements are first set to some incrementing value, then they are printed out. Ad-hoc access can be done by calling 'getref' directly, or dedicated 'getset' and 'setelem' routines can be used. At first it didn't look like this was a practical approach for Algol68 or any statically typed language. But I think that once you recourse to 'getset' and 'setelem' routines that take a vector of indices, then this can work elsewhere. Maybe this is the linearising you refered to. In any case, it all looks messy, whatever the language. -------------------------------------------------- var count = 0 proc main = v := (2, 3, 4, 5, 6) x := maketable(v) loopover(x, v, {p, i: p^ := ++count}) # {} is anon. func loopover(x, v, {p, i: println i, ":", p^; 0}) end func getref(data, indices)= x:=data for i in 1..indices.len-1 do x := x[indices[i]] end ^x[indices[$]] # $ is final index end proc loopover(data, vec, fn) = dim := vec.len iter := (1,)*dim !start at (1,1,1,...) do fn(getref(data, iter), iter) exit when iter = vec ++iter[dim] for i := dim downto 2 do if iter[i] > vec[i] then iter[i] := 1 ++iter[i-1] end end end end func maketable(vec) = if vec.len = 1 then new(list, head(vec), 0) else a := new(list, head(vec), maketable(tail(vec))) for i, x in a do a[i] := copy(x) end a end end