Dear Edd Barrett,
I'm afraid you've come across one of the ugliest parts of Maxima.
There are actually *two distinct kinds* of associative array in Maxima:
"hashed" associative arrays (which you get without declarations), and
"hash_table" associative arrays (which you get with make_array('hashed)).
Bizarrely and inexcusably, the semantics of these two kinds of arrays are
completely inconsistent.
The "hash_table" style is problematic in various ways and I would recommend
it be rethought and replaced.
In the meantime, though, you can define the following:
:lisp (defun $hash_table_defined (ar i) (multiple-value-bind (val ok)
(marrayref-gensub ar i nil) ok))
Then hash_table_defined( <<hash_table>>, <<index>> ) will return true or
false.
A simpler way to do this is just to make sure that FALSE is never a valid
value. Since you are storing lists of variables, how can FALSE ever be
valid?
-s
For example:
*Hashed style*
qq[3]: 5$
qq[3] => 5 OK
qq[7] => qq[7]
qq => qq << treated as an identifier, not as a first-class value
kill(qq[3]) OK
qq[3] => qq[3] restored to uninitialized state
arrayinfo(qq) => [hashed,1,[3]]
qq[5,5]: 999 => error -- must have consistent number of subscripts
*Hash_table style*
rr: make_array('hashed)$
rr[3]:5$
rr[3] => 5 OK
rr[7] => false <<< inconsistent
rr => {Lisp Array: #<hash-table 10d2408c>} << treated as a weird internal
object
kill(rr[3]) => error
arrayinfo(rr) => [hash_table,1,3] << notice inconsistent conventions
rr[5,5]: 999 => no error -- allows different numbers of subscripts
arrayinfo(rr) => fatal error (implementation bug)