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

Re: easy calling of associative array?




02.11.2015, 18:45, "Ray Andrews" <rayandrews@xxxxxxxxxxx>:
> On 11/01/2015 10:51 PM, Bart Schaefer wrote:
>>  Anyway, that's actually the point. ${(P)ref} resolves to the values of
>>  the array, and then the subscript is applied. Ask yourself: what are
>>  "the values of" an associative array, in every other context?
>
> I'll give it some time, this is new to me. It seems that with an
> associative array,
> what we have is some 'hidden' syntax, IOW there is a sort of shorthand going
> on. As with math, I'd sorta expect that if this functionality was
> tacked on
> after the fundamentals of the shell were already in place--you leveraged
> what was there--there'd be asymmetries.
>
> Experimenting with trying to make accessing associative arrays convenient:
>
>     echo_v ()
>     {
>     echo ${(P)${:-${1}[$2]}} #this works

    typeset -A foo
    foo=('abc]def' true)
    echo_v foo 'abc]def'
    # Echoes nothing in place of `true`.

. But `key='abc]def' ; echo $foo[$key]` works.

>     #eval "echo \$${1}[$2]" #and this works too.

Thus you need to eval in the following form:

    eval 'echo $'$1'[$2]'

. Without eval I have only came up with

    echo_v()
    {
        emulate -L zsh
        local -A array
        array=( ${(kvP)1} )
        echo $array[$2]
    }

>     }
>
>     get_v ()
>     {
>     #$3=${(P)${:-${1}[$2]}} #nothing works
>     eval "$3=\$${1}[$2]" #this works

Like previous function, but last line should be

        : ${(P)3::=$array[$2]}

in place of `echo $array[$2]`.

With eval you need to use

    eval $3'=$'$1'[$2]'

>     }
>
>     set_v ()
>     {
>     # {(P)${:-${1}[$2]}}=$3 #nothing works
>     eval "${1}[$2]=$3" #this works
>     }

    set_v()
    {
        emulate -L zsh
        local -A array
        array=( ${(kvP)1} $2 $3 )
        : ${(AAP)1::=${(kv)array}}
    }

Note that all my variants without eval are copying array around, eval variants do not.

Eval here:

    eval $1'[$2]=$3'

.

>
>     test_v ()
>     {
>     #eval "${1}[$2]" #nothing works
>                                  #this works
>     [ ${(P)${:-${1}[$2]}} = $3 ] && echo 'all too true' || echo 'alas, no.'

Pretty much obvious after `echo_v`. Note the same problem with 2='abc]def'

>     }
>
> I notice that with 'echo_v' I can use your syntax or 'eval' the thing
> which is
> much easier to read if nothing else. But with 'get_v' and 'set_v' I can
> only make
> it work with 'eval' whereas with 'test_v' I can *not* make it work with
> 'eval'.
> At the risk of being too much of a symmetry nut, is it possible to make
> either
> form work in all the above situations? If so, I have a consistent
> interface to
> these arrays which would be pleasing, but it's an academic point.

Not purely academic. With eval you automatically run in escaping problems (though rather easy to resolve in this case). Without eval you make your code rather unreadable.

>
> FWIW, this is in the context of studying Sebastian's stuff--there's all
> these
> variables sloshing about for each of several zcurses windows, and it
> would be
> C-ish to organize them into arrays, one for each window. However I can
> see that this is at the limits of what a shell should be asked to do, since
> what I really want is a proper C structure for data:
>
> main_window.window_height
>
> becomes:
>
> ${main_window[window_height]}
>
> ... but of course I want to be able to replace 'main_window' with
> any other window via a variable passed to whatever function:
>
> whatever_window->window_height
>
> becomes:
>
> ${(P)${:-${whatever_window}[window_height]}}
>
> ... which looks like it's going to work just so long as I can perform
> any sort
> of operation on the array without difficulty. But there could be speed
> issues
> and the whole thing might not be worth the trouble, but it is educational
> at least.

You can also always use zpython:

echo_v() zpython 'print(zsh.getvalue(zsh.getvalue("1")[0])[zsh.getvalue("2")[0]])'
get_v()  zpython 'zsh.setvalue(zsh.getvalue("3")[0], zsh.getvalue(zsh.getvalue("1")[0])[zsh.getvalue("2")[0]])'
set_v()  zpython 'ret = zsh.getvalue(zsh.getvalue("1")[0]); ret[zsh.getvalue("2")[0]]=zsh.getvalue("3")[0]; zsh.setvalue(zsh.getvalue("1")[0], ret)'

. Pretty much consistent (except that I have no idea why it thinks that all $N parameters are array parameters, but this is consistent with ${(t)1} which returns “array-special”). But again each function is copying parameters around.



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