* indirect array element assignment? @ 2022-07-02 10:33 Anthony Heading 2022-07-02 18:13 ` Bart Schaefer 0 siblings, 1 reply; 6+ messages in thread From: Anthony Heading @ 2022-07-02 10:33 UTC (permalink / raw) To: zsh-users What's the best zsh way of doing an indirect array element assignment? This works quite nicely in bash: #!/bin/bash fruits=("apple" "banana" "carrot") # but a carrot is not a fruit var="fruits" declare -n v=$var v[2]="cherry" echo ${fruits[@]} => apple banana cherry Everything in zsh I've tried around ${${(P)v}[2]::=cherry} with misc different bracketing gets "not an identifier", suggesting maybe the ::= form doesn't support subscripting. Is there something better than 'eval' for this? ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: indirect array element assignment? 2022-07-02 10:33 indirect array element assignment? Anthony Heading @ 2022-07-02 18:13 ` Bart Schaefer 2022-07-02 18:23 ` Bart Schaefer 2022-07-03 2:28 ` Anthony Heading 0 siblings, 2 replies; 6+ messages in thread From: Bart Schaefer @ 2022-07-02 18:13 UTC (permalink / raw) To: Anthony Heading; +Cc: Zsh Users On Sat, Jul 2, 2022 at 3:34 AM Anthony Heading <ajrh@ajrh.net> wrote: > > What's the best zsh way of doing an indirect array element assignment? fruits=("apple" "banana" "carrot") v=fruits typeset "${v}[3]"=cherry There really isn't a good solution if you're trying to do array slices, i.e., a parenthesized list on the right of the "=". > Everything in zsh I've tried around ${${(P)v}[2]::=cherry} with misc different bracketing gets "not an identifier", suggesting maybe the ::= form doesn't support subscripting. It's not that it doesn't support subscripting, it's that it doesn't support parameter expansions of any kind on the left: % echo ${${grape}::=raisin} zsh: not an identifier: I'm not sure why the error isn't more specific. The syntax, if it worked, would be ${(P)v[3]::=cherry}, because ${(AP)=v::=apple banana carrot} works, but although ${(P)v} gets you a reference to $fruits, as soon as you subscript it as ${(P)v[x]} you end up assigning to a copy of the x'th field of $fruits instead, because zsh doesn't create indirect references to array elements, it substitutes them by value. You can do it this way: z="${v}[3]" echo ${(P)z::=cherry} ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: indirect array element assignment? 2022-07-02 18:13 ` Bart Schaefer @ 2022-07-02 18:23 ` Bart Schaefer 2022-07-03 2:28 ` Anthony Heading 1 sibling, 0 replies; 6+ messages in thread From: Bart Schaefer @ 2022-07-02 18:23 UTC (permalink / raw) To: Anthony Heading; +Cc: Zsh Users On Sat, Jul 2, 2022 at 11:13 AM Bart Schaefer <schaefer@brasslantern.com> wrote: > > The syntax, if it worked, would be ${(P)v[3]::=cherry} I'm sorry, I just realized that's wrong. $v is a scalar, so v[3] is the letter "u" (third character of "fruits") and this assigns to the variable $u. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: indirect array element assignment? 2022-07-02 18:13 ` Bart Schaefer 2022-07-02 18:23 ` Bart Schaefer @ 2022-07-03 2:28 ` Anthony Heading 2022-07-03 3:41 ` Bart Schaefer 1 sibling, 1 reply; 6+ messages in thread From: Anthony Heading @ 2022-07-03 2:28 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh Users On Sat, Jul 2, 2022, at 2:13 PM, Bart Schaefer wrote: > You can do it this way: > > z="${v}[3]" > echo ${(P)z::=cherry} Wow. Thank you! I didn't think of that at all. > It's not that it doesn't support subscripting, it's that it doesn't > support parameter expansions of any kind on the left: > > % echo ${${grape}::=raisin} > zsh: not an identifier: Ah, that makes sense. Though hmm... there's some lhs expansion, no? ${grape[$#grape]::=raisin} for example. Is it a necessary error by design? I see why the (P) flag is needed for rhs expansion because shell ${${${...}}} defines nesting to mean something different, but for lhs ::= I wonder why ${${X}::=...} couldn't have well-defined natural meaning. > There really isn't a good solution if you're trying to do array > slices, i.e., a parenthesized list on the right of the "=". You're referring to the typeset style solution here, maybe? Your later solution seems to work great for all sorts of array splicing. fruits=(apple banana carrot calamansi cherry cantaloupe durian) # hunt down the errant vegetable and all its friends v="fruits" z="${v}[(r)c*,(R)c*]" : ${(PA)z::=$signals[10,11]} echo $fruits % apple banana KILL USR1 durian ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: indirect array element assignment? 2022-07-03 2:28 ` Anthony Heading @ 2022-07-03 3:41 ` Bart Schaefer 2022-07-03 16:43 ` Anthony Heading 0 siblings, 1 reply; 6+ messages in thread From: Bart Schaefer @ 2022-07-03 3:41 UTC (permalink / raw) To: Anthony Heading; +Cc: Zsh Users On Sat, Jul 2, 2022 at 7:28 PM Anthony Heading <ajrh@ajrh.net> wrote: > > On Sat, Jul 2, 2022, at 2:13 PM, Bart Schaefer wrote: > > It's not that it doesn't support subscripting, it's that it doesn't > > support parameter expansions of any kind on the left: > > > > % echo ${${grape}::=raisin} > > zsh: not an identifier: > > Ah, that makes sense. Though hmm... there's some lhs expansion, no? > ${grape[$#grape]::=raisin} for example. Subscripting does expansion inside the [ ], but that's not the same context as ${${...}}. > Is it a necessary error by design? ... for lhs ::= I wonder > why ${${X}::=...} couldn't have well-defined natural meaning. For that to work, ${${X}} would have to mean the same as ${(P)X}. As a general rule nested expansions are processed innermost-leftmost, and substitute rvalues rather than lvalues. The (P) is what forces the current level of expansion to turn into an lvalue, but that doesn't apply to either the surrounding or the surrounded levels. So ${(P)${X}::=thing} actually does work as long as ${X} returns a valid identifier that can be treated as an lvalue. Without the (P) it remains an rvalue and you get the "not an identifier" error. (I'm glossing over a lot of what actually goes on underneath here, but if you're familiar with the concepts of lvalues and rvalues this is a pretty good way to think about it.) That does in fact mean that this works too, now that I think of it: ${(P)${:-${v}[2]}::=mango} > > There really isn't a good solution if you're trying to do array > > slices, i.e., a parenthesized list on the right of the "=". > > You're referring to the typeset style solution here, maybe? Yes. > Your later solution seems to work great for all sorts of array splicing. Sure, but you also have to do your own array splitting, as e.g. ${(AP)=v::=apple banana carrot}, if attempting to assign a plain list of words. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: indirect array element assignment? 2022-07-03 3:41 ` Bart Schaefer @ 2022-07-03 16:43 ` Anthony Heading 0 siblings, 0 replies; 6+ messages in thread From: Anthony Heading @ 2022-07-03 16:43 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh Users On Sat, Jul 2, 2022, at 11:41 PM, Bart Schaefer wrote: > That does in fact mean that this works too, now that I think of it: > > ${(P)${:-${v}[2]}::=mango} Even better! Though gosh it does start to cry out for dedicated assignment syntax/parsing. I always though it was rather a pity that some predecessor (ksh maybe?) claimed 'let' for arithmetic so it's not free: let ${v}[2] ?= (peach apricot) etc would be easier to deal with. But perhaps this was the thought-process that unleashed csh on the world, so maybe not. > For that to work, ${${X}} would have to mean the same as ${(P)X}. As > a general rule nested expansions are processed innermost-leftmost, and > substitute rvalues rather than lvalues. Yes. It didn't seem *too* far off, but I traced it now with gdb through paramsubst() and I follow what you mean. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-07-03 16:45 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-07-02 10:33 indirect array element assignment? Anthony Heading 2022-07-02 18:13 ` Bart Schaefer 2022-07-02 18:23 ` Bart Schaefer 2022-07-03 2:28 ` Anthony Heading 2022-07-03 3:41 ` Bart Schaefer 2022-07-03 16:43 ` Anthony Heading
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).