can't push into a list in an array ?

Started by dave_f, January 07, 2008, 06:53:06 PM

Previous topic - Next topic

dave_f

First, I made an array of five empty lists.  Then I tried to add an element to one of the lists in the array, using push.  It didn't work, and I would like to understand why not.  Here's the story:



> (set 'A-of-L (array 5 '(()) ))

(() () () () ())

> (push 'a  (A-of-L 2))

a

> A-of-L

(() () () () ())

> (A-of-L 2)

()



Sorry if this is clueless-newbie question!



thanks,



dave_f



newLISP 9.2.12

Mac OS 10.4.11

Intel iMac

Cyril

#1
Quote from: "dave_f"First, I made an array of five empty lists.  Then I tried to add an element to one of the lists in the array, using push.  It didn't work, and I would like to understand why not.


Because newLISP, unlike other lisp's (Common Lisp, Scheme) and unlike most of the dynamic languages (Python, Ruby) does copying values, not references. '(A-of-L 2)' returns not the "same" empty list that is hold by an array, but a fresh copy of empty list. 'push' modifies this fresh copy and then loses it. If you want to modify a list buried deeply in nested list structure, you can use additional indices as arguments to 'push' (or other destructive functions), but if list is nested into array -- I believe there are no way to do it. Can anyone disprove this?
With newLISP you can grow your lists from the right side!

Cyril

#2
BTW, here is question to community and to Lutz especially: is the current approach of nested indexing of mixed array and list structures good enough? If someone have a nested list, he can index it as (mylist 2 3 4), for a multidimensional array (myarray 2 3 4) works also, but for an array nested into list and vice versa this fails. And, the worse of all, it doesn't even signal an error, superfluous indices are just dropped. I believe that not signaling errors is a bad practice. Changing the out-of-range index behavior in 9.2.12 (not tested yet, just read announce) is a good step, can we (and shall we) continue in this direction?



To be clear: there is two different and independent suggestions: (1) to allow mixed list and array structures be transparently indexed (2) to signal superfluous indices as an error. They may be considered independedly.
With newLISP you can grow your lists from the right side!

Lutz

#3
Quoteallow mixed list and array structures be transparently indexed


This could lead to ambiguous situations. But when this is the intention, do: ((array 1 2) 3) or (nth 3 (array 1 2))


Quotesignal superfluous indices as an error


Perhaps ... not sure on this one. Personally when working with nested lists, I prefer the current behavior of dropping superfluous indices.



Lutz

cormullion

#4
Dave, try nth-set to set the value of the cell of the array:


(nth-set (A-of-L 2) 23)

If you do this:


(set 'A-of-L (array 5 (map char (sequence 65 70))))

followed by this:


(A-of-L  2)

you're going to get a string:


"C"

Then after this:


(push "23" (A-of-L 2) -1)

you've pushed "23" to the end of "C", then thrown the result - "C23" away.



push returns only the inserted element, so it's not quite what you want.



To add something to the end of an array element, you could use something like this:


(nth-set (A-of-L 2) (append (A-of-L 2) "suffix"))

Personally I avoid using arrays as far as possible; I don't need the speed advantage, and I think that they're slightly less versatile. With lists, you know you're on safe ground with newLISP, and most of the really cool features work on lists but not always on arrays (although Lutz likes to narrow the gap sometimes)



In fact, when I was doing some maze drawing stuff, I used this code:


(set  'height 40
        'width 40
        'wall-length 20
        'maze (array-list (array height width '("ensw"))))


which looks as if I'm using arrays purely for the cool initialization... :)

Cyril

#5
Quote from: "Lutz"But when this is the intention, do: ((array 1 2) 3) or (nth 3 (array 1 2))


No problem while accessing a deeply nesting structure. Hard problem when trying to modify it. In more traditional languages, accessor yields a reference to inner structure (array or list or something), and you can modify it as you like. In newLISP there are no references (at least, no ubiquitous references), and the task of modifying a deeply nested structure is solved by lists of indices. This work consistent with all operations on nested lists and/or nested arrays (thanks, Lutz!), but it fails on mixed array/list structures. Such a beasts became in fact immutable (you can only take an inner thing in whole and replace it with modified version, but not modify one element of it). This seems illogical and inconvenient for me.
With newLISP you can grow your lists from the right side!

cormullion

#6
I'm still unsure about arrays - but I've never thought of using mixed array/list structures. As you say, they must be beasts - but isn't the only reason to use arrays one of speed - and are mixed array/list structures any faster than standard lists?



I have only limited applications for newLISP - text processing, blogging engine, etc - so can't imagine the benefits of using an array/list structure...



I believe you can pass lists by reference - never done that either, though±