Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: associative array questions



On Sun, Dec 11, 2022 at 9:40 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
>
>[...] C-brained as I am, I'm wanting to link to
> the input array directly via a pointer sort of operation so in test3 I'm
> trying to grab the name of the target array and modify it (the array)
> directly.

There are no pointers to data structures in zsh.  Parameter reference
is always by value.  Even ${(P)other} returns a value, it's just the
value of the parameter whose name is in turn the value of $other.
Anything you do with the result of ${(P)other} acts on that value, not
on the indirectly-named parameter itself.

There is one sort-of exception:  The ${NAME=WORD} and related
assign-and-substitute operations.  E.g., if you use
${(P)other::=text}, then the parameter named by $other is assigned the
value "text".  I say this is only sort-of an exception because if
$other names an array, you can only assign to the entire array, not to
individual subscripted fields.

If you want to assign indirectly to a particular field (whether a
position in an ordinary array or a named element in an associative)
you have to store the entire subscript expression in $other, such as
  other="aa[second]"
  : ${(P)other::='tea for two'}

>      print "aa[second] is: ${${(P)aarray}[second]}"

Incidentally, this doesn't work in zsh earlier than 5.2.  Even in 5.9,
it doesn't carry over into the ${NAME=WORD} construct.

> # BAD:
> #    ${(P)aarray}[second]='tea for two'

Assignments are only parsed as such when there is an identifier
(string of nothing but alphanumerics or underscore, plus optional
subscript) to the left of the equal sign BEFORE any substitutions are
performed.  So this doesn't "look like" an assignment to the parser.

Lacking the outer ${...} enclosing the subscript, ${(P)aarray} expands
to all the values of the pointed-to associative array, and you get the
equivalent of

  "1" "two" "three blind mice"[second]

> # GOOD:
>      eval "${aarray}[second]='tea for two'"

In this case the "eval" turns the command into

  aa[second]='tea for two'

which satisfies the "identifier to the left" rule.

You could also do (another thing that doesn't work in older zsh)

  eval "${aarray}+=([second]='tea for two')"

> '${(P)aarray'} should expand to 'aa' remembering that it's a variable

Nope.  It expands to a value, not a variable reference.  Zsh doesn't
(yet) have what ksh calls "namerefs" ... block out everything you know
about pointers in C.

> also unexpected that the array prints upside down:

Associative arrays are unordered hash tables.  It might print "upside
down" or "inside out" depending on what keys are present.  They're
only even called "arrays" because that's how the value behaves if you
omit the subscript.




Messages sorted by: Reverse Date, Date, Thread, Author