* easy calling of associative array? @ 2015-11-01 23:12 Ray Andrews 2015-11-01 23:55 ` ZyX 0 siblings, 1 reply; 20+ messages in thread From: Ray Andrews @ 2015-11-01 23:12 UTC (permalink / raw) To: Zsh Users test () { eval "baz=\$${1}[key1]" echo $baz eval "foo=\$${1}[key2]" echo $foo ... } If I want to pass the name of an associative array to a function via "$1" and then work with it's keys, the above succeeds but it's sure laborious. Is there some way to do the eval just once? So that I can end up doing: if [ "xyz[key1]" = '1' ]; then ... ... as I experiment, there seems to be no way of replacing 'xyz' with any expression that will do the job without needing eval's help every time, but I'll bet there's a way. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-01 23:12 easy calling of associative array? Ray Andrews @ 2015-11-01 23:55 ` ZyX 2015-11-02 0:49 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: ZyX @ 2015-11-01 23:55 UTC (permalink / raw) To: Ray Andrews, Zsh Users 02.11.2015, 02:44, "Ray Andrews" <rayandrews@eastlink.ca>: > test () > { > eval "baz=\$${1}[key1]" > echo $baz > eval "foo=\$${1}[key2]" > echo $foo > ... > } > > If I want to pass the name of an associative array to a function via > "$1" and then work with it's keys, the above succeeds but it's sure > laborious. Is there some way to do the eval just once? So that I can > end up doing: > > if [ "xyz[key1]" = '1' ]; then ... > > ... as I experiment, there seems to be no way of replacing 'xyz' with > any expression that will do the job without needing eval's help every > time, but I'll bet there's a way. There is ${(P)} for indirect referencing: % foo=path % echo ${${(P)foo}[1]} $path[1] /home/zyx/.local/bin /home/zyx/.local/bin . This is in `man zshexpn`. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-01 23:55 ` ZyX @ 2015-11-02 0:49 ` Ray Andrews 2015-11-02 3:08 ` Bart Schaefer 0 siblings, 1 reply; 20+ messages in thread From: Ray Andrews @ 2015-11-02 0:49 UTC (permalink / raw) To: zsh-users On 11/01/2015 03:55 PM, ZyX wrote: > 02.11.2015, 02:44, "Ray Andrews" <rayandrews@eastlink.ca>: > > There is ${(P)} for indirect referencing: > > % foo=path > % echo ${${(P)foo}[1]} $path[1] > /home/zyx/.local/bin /home/zyx/.local/bin > > . This is in `man zshexpn`. > I can't get it to work with associative arrays tho. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 0:49 ` Ray Andrews @ 2015-11-02 3:08 ` Bart Schaefer 2015-11-02 3:33 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-02 3:08 UTC (permalink / raw) To: zsh-users On Nov 1, 4:49pm, Ray Andrews wrote: } Subject: Re: easy calling of associative array? } } On 11/01/2015 03:55 PM, ZyX wrote: } > } > There is ${(P)} for indirect referencing: } } I can't get it to work with associative arrays tho. Yeah, it's a bit weird with associative arrays because everything is passed by value. ${(P)ref} is ${(vP)ref} and thus ${${(P)ref}[idx]} doesn't get what you want, and ${(P)ref[idx]} is ${(P)${ref[idx]}} which also isn't what you want. So you have to get a little arcane: ${(P)${:-${ref}[idx]}}. - ${ref} is the name of the assocative array. - ${ref}[idx] is therefore a string that has the same format as the array lookup you want to perform. - ${:-${ref}[idx]} substitutes that string into a parameter expansion. - ${(P)${:-${ref}[idx]}} then treats that substitution as another parameter expansion, and you end up where you wanted to be. This is admittedly not ideal, but until we embark on a significant rewrite of parameter expansion, we're stuck maneuvering values into the right places at the right times. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 3:08 ` Bart Schaefer @ 2015-11-02 3:33 ` Ray Andrews 2015-11-02 6:51 ` Bart Schaefer 0 siblings, 1 reply; 20+ messages in thread From: Ray Andrews @ 2015-11-02 3:33 UTC (permalink / raw) To: zsh-users On 11/01/2015 07:08 PM, Bart Schaefer wrote: > - ${(P)${:-${ref}[idx]}} then treats that substitution as another > parameter expansion, and you end up where you wanted to be. Deus avertat. But what would prevent this from being parsed?: ${${ref}[idx]} or even: ${${ref}[$idx]} ... since an expansion can be used in the back end just fine already. I dunno, but the above seems at least naively straight forward. Also, that form works with normal arrays. But if you say it can't work that way I can't say otherwise, of course. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 3:33 ` Ray Andrews @ 2015-11-02 6:51 ` Bart Schaefer 2015-11-02 15:43 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-02 6:51 UTC (permalink / raw) To: zsh-users On Nov 1, 7:33pm, Ray Andrews wrote: } } But what would prevent this from being parsed?: } } ${${ref}[idx]} } ${${ref}[$idx]} Those both ARE parsed. The problem is, that form is defined to mean something different than what it would have to mean for it to work in (P) context. It's not a parsing issue. } Also, that form works with normal arrays. Presuming you mean ${${(P)ref}[idx]}, because it means something else if you leave out the (P) or put it somewhere else. 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? ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 6:51 ` Bart Schaefer @ 2015-11-02 15:43 ` Ray Andrews 2015-11-02 16:28 ` Bart Schaefer 2015-11-02 19:33 ` ZyX 0 siblings, 2 replies; 20+ messages in thread From: Ray Andrews @ 2015-11-02 15:43 UTC (permalink / raw) To: zsh-users 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 #eval "echo \$${1}[$2]" #and this works too. } get_v () { #$3=${(P)${:-${1}[$2]}} #nothing works eval "$3=\$${1}[$2]" #this works } set_v () { # {(P)${:-${1}[$2]}}=$3 #nothing works eval "${1}[$2]=$3" #this works } test_v () { #eval "${1}[$2]" #nothing works #this works [ ${(P)${:-${1}[$2]}} = $3 ] && echo 'all too true' || echo 'alas, no.' } 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. 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. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 15:43 ` Ray Andrews @ 2015-11-02 16:28 ` Bart Schaefer 2015-11-02 18:32 ` Ray Andrews 2015-11-02 19:33 ` ZyX 1 sibling, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-02 16:28 UTC (permalink / raw) To: zsh-users On Nov 2, 7:43am, Ray Andrews wrote: } } get_v () } { } #$3=${(P)${:-${1}[$2]}} #nothing works } eval "$3=\$${1}[$2]" #this works } } This has nothing to do with associative arrays and everything to do with assignment syntax. "$3" is not a valid identifier, so "$3=" is not an assignment; this all decided before $3 is expanded, which is why putting the "eval" around it works (it delays the "is an identifier" check until after $3 has expanded). Probably the most cogent way to do this is get_v () { typeset -g $3="${(P)${:-${1}[$2]}}" } } set_v () } { } # {(P)${:-${1}[$2]}}=$3 #nothing works } eval "${1}[$2]=$3" #this works } } Same assignment-syntax problem. set_v () { # typeset -gA $1 # optional typeset -g "${1}[$2]=$3" # quotes so [ ] isn't globbing } Here you don't need the (P) indirection because ${1} and $2 are both expanded before being passed to typeset, so you already extracted the name that was passed in $1. Also note I'm ignoring all possible error checking, e.g. if $1 is not an identifier (in the worst case, contains an "="), things go badly. } test_v () } { } #eval "${1}[$2]" #nothing works } #this works } [ ${(P)${:-${1}[$2]}} = $3 ] && echo 'all too true' || echo 'alas, no.' } } I'm not exactly sure what you're wanting as either output or exit status here, but except that I'd recommend [[ ]] instead of [ ] as the test syntax, what you wrote for "this works" is sensible. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 16:28 ` Bart Schaefer @ 2015-11-02 18:32 ` Ray Andrews 2015-11-02 19:37 ` ZyX 2015-11-02 21:05 ` Bart Schaefer 0 siblings, 2 replies; 20+ messages in thread From: Ray Andrews @ 2015-11-02 18:32 UTC (permalink / raw) To: zsh-users On 11/02/2015 08:28 AM, Bart Schaefer wrote: > } #$3=${(P)${:-${1}[$2]}} #nothing works Pardon, that was an obvious mistake. Too much thrashing around with 'eval'. > Same assignment-syntax problem. > > set_v () { > typeset -g "${1}[$2]=$3" # quotes so [ ] isn't globbing > } > > Here you don't need the (P) indirection because ${1} and $2 are both > expanded before being passed to typeset, so you already extracted the > name that was passed in $1. ... and that's nicely readable too--the sort of syntax that seems intuitive, as I mentioned. I won't say this is all clear in my mind, but it's at least tractable. One further question: I've never seen 'typeset' used to refer to anything but a simple variable. I note that the above does not work without the 'typeset -g' so what does that accomplish? I've never thought of the positional parameters and being typeset-able. I get the feeling it is a future problem solver. > > Also note I'm ignoring all possible error checking, e.g. if $1 is not > an identifier (in the worst case, contains an "="), things go badly. Sure, it's naive at this point. I don't yet think past that. > I'm not exactly sure what you're wanting as either output or exit > status here, but except that I'd recommend [[ ]] instead of [ ] as > the test syntax, what you wrote for "this works" is sensible. Ok. I don't pay enough attention to the difference. BTW, as a point of list etiquette: Responding to most posts I let my lines wrap but resonding to yours, which seem to alway have fixed line width, I try to match that style, but looking at the returned posts from the list, they sometimes sproing badly. Should I try to keep to your width, or just let lines wrap? > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 18:32 ` Ray Andrews @ 2015-11-02 19:37 ` ZyX 2015-11-02 22:10 ` Bart Schaefer 2015-11-02 21:05 ` Bart Schaefer 1 sibling, 1 reply; 20+ messages in thread From: ZyX @ 2015-11-02 19:37 UTC (permalink / raw) To: Ray Andrews, zsh-users 02.11.2015, 22:03, "Ray Andrews" <rayandrews@eastlink.ca>: > On 11/02/2015 08:28 AM, Bart Schaefer wrote: >> } #$3=${(P)${:-${1}[$2]}} #nothing works > > Pardon, that was an obvious mistake. Too much thrashing around with 'eval'. >> Same assignment-syntax problem. >> >> set_v () { >> typeset -g "${1}[$2]=$3" # quotes so [ ] isn't globbing >> } >> >> Here you don't need the (P) indirection because ${1} and $2 are both >> expanded before being passed to typeset, so you already extracted the >> name that was passed in $1. > > ... and that's nicely readable too--the sort of syntax that seems > intuitive, as I > mentioned. I won't say this is all clear in my mind, but it's > at least tractable. One further question: I've never seen 'typeset' > used to refer > to anything but a simple variable. I note that the above does not work > without > the 'typeset -g' so what does that accomplish? I've never thought of the > positional parameters and being typeset-able. I get the feeling it is a > future > problem solver. Typeset variant has unresolved problems with `$2` escaping. Writing `${(q)2}` works here, but I have no idea why it works. Note: when trying to use any of the functions, try with keys `abc]def` and `abc def` (two spaces inside). First collects most of the errors. >> Also note I'm ignoring all possible error checking, e.g. if $1 is not >> an identifier (in the worst case, contains an "="), things go badly. > > Sure, it's naive at this point. I don't yet think past that. >> I'm not exactly sure what you're wanting as either output or exit >> status here, but except that I'd recommend [[ ]] instead of [ ] as >> the test syntax, what you wrote for "this works" is sensible. > > Ok. I don't pay enough attention to the difference. > > BTW, as a point of list etiquette: Responding to most posts I let my > lines wrap > but resonding to yours, which seem to alway have fixed line width, I try to > match that style, but looking at the returned posts from the list, they > sometimes > sproing badly. Should I try to keep to your width, or just let lines wrap? >> ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 19:37 ` ZyX @ 2015-11-02 22:10 ` Bart Schaefer 2015-11-02 22:50 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-02 22:10 UTC (permalink / raw) To: zsh-users These should be robust for Zyx's failure cases (and throw errors in some other strange cases where they should). In older zsh where the (b) flag is not present, (q) will work in MOST cases. echo_v () { [[ -n $1 ]] && (( ${(P)+1} )) && print -R "${(P)${:-${1}[${(b)2}]}}" } get_v () { [[ -n $1 && $3 != *=* ]] && (( ${(P)+1} )) && typeset -g "${3:-REPLY}=${(P)${:-${1}[${(b)2}]}}" } set_v () { [[ -n $1 ]] && (( ${(P)+1} )) && typeset -g "${1}[${(b)2}]=$3" } test_v () { [[ -n $1 ]] && (( ${(P)+1} )) && [[ ${(P)${:-${1}[${(b)2}]}} = $3 ]] } ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 22:10 ` Bart Schaefer @ 2015-11-02 22:50 ` Ray Andrews 0 siblings, 0 replies; 20+ messages in thread From: Ray Andrews @ 2015-11-02 22:50 UTC (permalink / raw) To: zsh-users On 11/02/2015 02:10 PM, Bart Schaefer wrote: > echo_v () { > [[ -n $1 ]] && (( ${(P)+1} )) && > print -R "${(P)${:-${1}[${(b)2}]}}" > } > > get_v () { > [[ -n $1 && $3 != *=* ]] && (( ${(P)+1} )) && > typeset -g "${3:-REPLY}=${(P)${:-${1}[${(b)2}]}}" > } > As Peter once observed, there are no obfuscated code contests in zsh ;-) ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 18:32 ` Ray Andrews 2015-11-02 19:37 ` ZyX @ 2015-11-02 21:05 ` Bart Schaefer 2015-11-02 23:01 ` Ray Andrews 1 sibling, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-02 21:05 UTC (permalink / raw) To: zsh-users On Nov 2, 10:32am, Ray Andrews wrote: } Subject: Re: easy calling of associative array? } } On 11/02/2015 08:28 AM, Bart Schaefer wrote: } > } > set_v () { } > typeset -g "${1}[$2]=$3" # quotes so [ ] isn't globbing } > } } } I've never seen 'typeset' used to refer to anything but a simple } variable. In the above, set_v ary idx val is going to invoke typeset -g ary[idx]=val because $1 $2 $3 are all expanded after parsing and before calling the typeset command. (Zyx has pointed out the lack of robustness.) Note that it is not affecting any positional parameters, they're all long gone (replace by their values) before typeset begins. } I note that the above does not work without the 'typeset -g' so what } does that accomplish? Ordinarly "typeset" inside a function body behaves like "local". The -g option tells it not to do that, so that the name "ary" is taken to come from the calling context instead of the current function context. } BTW, as a point of list etiquette: Responding to most posts I let my } lines wrap } but resonding to yours, which seem to alway have fixed line width, I try to } match that style, but looking at the returned posts from the list, they } sometimes } sproing badly. Should I try to keep to your width, or just let lines wrap? The above is what your text would look like if I didn't run it through a reformatter. It Used To Be that everyone assumed text should be folded to be readable on an 80-column display, which, as a guy still using the email program I wrote myself 20 years ago, I still do. Then along came HTML format email, and everybody assumed text should never be wrapped at all (let the reader's UI deal with it). Except there's still this pesky thing about mailing lists preferring plain text, so we end up with a hypbrid where text as you write it is folded to be readable at whatever your display width is set, but then it gets re-folded to 80 when you send it -- except that it also keeps any real newlines you entered, so if you were actually trying to make it look nice, it ends up like the above instead. Exactly what you SHOULD do depends on what you're using to write your email. In Thunderbird you should probably put literal line breaks only at the ends of paragraphs, and let it wrap other stuff as it wills. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 21:05 ` Bart Schaefer @ 2015-11-02 23:01 ` Ray Andrews 2015-11-03 15:57 ` Bart Schaefer 0 siblings, 1 reply; 20+ messages in thread From: Ray Andrews @ 2015-11-02 23:01 UTC (permalink / raw) To: zsh-users On 11/02/2015 01:05 PM, Bart Schaefer wrote: > } > typeset -g "${1}[$2]=$3" # quotes so [ ] isn't globbing > In the above, > > set_v ary idx val > > is going to invoke > > typeset -g ary[idx]=val > > Ordinarly "typeset" inside a function body behaves like "local". The > -g option tells it not to do that, so that the name "ary" is taken to > come from the calling context instead of the current function context. I don't understand. The idea of context here is new to me. Why is 'ary' not a variable like any other? > } BTW, as a point of list etiquette: Responding to most posts I let my > } lines wrap > } but resonding to yours, which seem to alway have fixed line width, I try to > } match that style, but looking at the returned posts from the list, they > } sometimes > } sproing badly. Should I try to keep to your width, or just let lines wrap? > > The above is what your text would look like if I didn't run it through > a reformatter. It Used To Be that everyone assumed text should be > folded to be readable on an 80-column display, which, as a guy still > using the email program I wrote myself 20 years ago, I still do. Then > along came HTML format email, and everybody assumed text should never be > wrapped at all (let the reader's UI deal with it). Except there's still > this pesky thing about mailing lists preferring plain text, so we end up > with a hypbrid where text as you write it is folded to be readable at > whatever your display width is set, but then it gets re-folded to 80 > when you send it -- except that it also keeps any real newlines you > entered, so if you were actually trying to make it look nice, it ends > up like the above instead. Yes. Very unfortunate. > > Exactly what you SHOULD do depends on what you're using to write your > email. In Thunderbird you should probably put literal line breaks only > at the ends of paragraphs, and let it wrap other stuff as it wills. Ok. Gotta get a better program, I hate Tbird. > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 23:01 ` Ray Andrews @ 2015-11-03 15:57 ` Bart Schaefer 2015-11-04 14:48 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-03 15:57 UTC (permalink / raw) To: zsh-users On Nov 2, 3:01pm, Ray Andrews wrote: } Subject: Re: easy calling of associative array? } } On 11/02/2015 01:05 PM, Bart Schaefer wrote: } > } > typeset -g ary[idx]=val } > } > Ordinarly "typeset" inside a function body behaves like "local". The } > -g option tells it not to do that, so that the name "ary" is taken to } > come from the calling context instead of the current function context. } } I don't understand. The idea of context here is new to me. Why is } 'ary' not a variable like any other? Parameters have dynamic scope from the function call (not the function name) where they are declared. So if you have a function "upper" that calls a function "middle" that calls a function "lower", a parameter that is declared in "middle" is visible to "lower" but not to "upper", and a parameter declared in "upper" is visible to both "middle" and "lower". "typeset" is the generic "declare a parameter" builtin. All of the other builtins (delcare, local, integer, etc.) are special cases of "typeset". So if both "upper" and "middle" contain "typeset -A ary", the name "ary" in "middle" is now a new variable, not the same as the "ary" in "upper". This is exactly like saying "local ary" in "middle", becuse "local" is really a form of "typeset", merely given another name to make it more obvious what's happening. Using "typeset -gA ary" in "middle" prevents this; it says "don't declare a new local parameter, use the one that is already in scope." The usage with "-g ary[idx]" says "don't attempt to index into a new local parameter $ary, instead index into the existing $ary if there is one." Which is what you want if the name "ary" has been passed down through $1. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-03 15:57 ` Bart Schaefer @ 2015-11-04 14:48 ` Ray Andrews 2015-11-04 16:39 ` Bart Schaefer 0 siblings, 1 reply; 20+ messages in thread From: Ray Andrews @ 2015-11-04 14:48 UTC (permalink / raw) To: zsh-users On 11/03/2015 07:57 AM, Bart Schaefer wrote: > Using "typeset -gA ary" in "middle" prevents this; it says "don't declare > a new local parameter, use the one that is already in scope." > > The usage with "-g ary[idx]" says "don't attempt to index into a new local > parameter $ary, instead index into the existing $ary if there is one." > Which is what you want if the name "ary" has been passed down through $1. > Ok, that's quite clear. Thanks Bart. Historian that I am, I expect that if the writers of the first shells realized how far their work would evolve, they'd have introduced rigorous C-ish scoping and typing at the getgo, since largeish projects sure could use it. One is often unsure what is going on with variables when there are several levels of functions. This use of typeset sounds like excellent insurance. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-04 14:48 ` Ray Andrews @ 2015-11-04 16:39 ` Bart Schaefer 2015-11-04 18:31 ` Ray Andrews 0 siblings, 1 reply; 20+ messages in thread From: Bart Schaefer @ 2015-11-04 16:39 UTC (permalink / raw) To: zsh-users On Nov 4, 6:48am, Ray Andrews wrote: } } Historian that I am, I expect that if the writers of the first shells } realized how far their work would evolve, they'd have introduced } rigorous C-ish scoping and typing at the getgo, since largeish } projects sure could use it. Historically no one would have written that sort of project in shell; that's what C was for. Even functions are a bolt-on to the original shells; there was no scoping to consider at the time. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-04 16:39 ` Bart Schaefer @ 2015-11-04 18:31 ` Ray Andrews 0 siblings, 0 replies; 20+ messages in thread From: Ray Andrews @ 2015-11-04 18:31 UTC (permalink / raw) To: zsh-users On 11/04/2015 08:39 AM, Bart Schaefer wrote: > On Nov 4, 6:48am, Ray Andrews wrote: > } > } Historian that I am, I expect that if the writers of the first shells > } realized how far their work would evolve, they'd have introduced > } rigorous C-ish scoping and typing at the getgo, since largeish > } projects sure could use it. > > Historically no one would have written that sort of project in shell; > that's what C was for. Even functions are a bolt-on to the original > shells; there was no scoping to consider at the time. Yeah, that's about what I was saying. Interesting how things evolve past what their body plans are really designed for (fruit bats, rhinoceros beetles, London street plan), and how those body plans adapt to cope with it. I do now quite understand that there is a limit to how big a zsh project should get to be. Still you know, will all these fantastic little build in manipulations that zsh can perform, one might long for something that combines that power with the robustness of C type checking and so on. Dunno, maybe that's Python or Ruby--haven't looked at them yet. But the experiments I'm doing now are cool, I've pretty much got data arrays being passed by what more or less amounts to a 'pointer' to look at it tho of course it ain't really a pointer, so it satisfies. > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 15:43 ` Ray Andrews 2015-11-02 16:28 ` Bart Schaefer @ 2015-11-02 19:33 ` ZyX 2015-11-02 23:04 ` Ray Andrews 1 sibling, 1 reply; 20+ messages in thread From: ZyX @ 2015-11-02 19:33 UTC (permalink / raw) To: Ray Andrews, zsh-users 02.11.2015, 18:45, "Ray Andrews" <rayandrews@eastlink.ca>: > 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. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: easy calling of associative array? 2015-11-02 19:33 ` ZyX @ 2015-11-02 23:04 ` Ray Andrews 0 siblings, 0 replies; 20+ messages in thread From: Ray Andrews @ 2015-11-02 23:04 UTC (permalink / raw) To: zsh-users On 11/02/2015 11:33 AM, ZyX wrote: Thanks for at that ZyX, it will take a while to digest. ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2015-11-04 18:31 UTC | newest] Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-11-01 23:12 easy calling of associative array? Ray Andrews 2015-11-01 23:55 ` ZyX 2015-11-02 0:49 ` Ray Andrews 2015-11-02 3:08 ` Bart Schaefer 2015-11-02 3:33 ` Ray Andrews 2015-11-02 6:51 ` Bart Schaefer 2015-11-02 15:43 ` Ray Andrews 2015-11-02 16:28 ` Bart Schaefer 2015-11-02 18:32 ` Ray Andrews 2015-11-02 19:37 ` ZyX 2015-11-02 22:10 ` Bart Schaefer 2015-11-02 22:50 ` Ray Andrews 2015-11-02 21:05 ` Bart Schaefer 2015-11-02 23:01 ` Ray Andrews 2015-11-03 15:57 ` Bart Schaefer 2015-11-04 14:48 ` Ray Andrews 2015-11-04 16:39 ` Bart Schaefer 2015-11-04 18:31 ` Ray Andrews 2015-11-02 19:33 ` ZyX 2015-11-02 23:04 ` Ray Andrews
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).