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

Re: saved from prince of eval



On 11/08/2015 11:57 AM, Bart Schaefer wrote:
If you haven't already, you should read through the "Rules" section
under "Parameter Expansion".  "man zshexpn" and search for "Rules".

Indeed. I've bounced off it several times, it's the thickest of the thick. Yes, I'll bone up and master it.
In particular the last sentence of the #1 rule "Nested Substitution":

      ... Note  that,  unless  the  '(P)'
      flag is present, the flags and any subscripts apply directly to
      the value of the nested substitution; for example,  the  expan-
      sion ${${foo}} behaves exactly the same as ${foo}.

Then note that (e) isn't applied until nearly the end of the procedure,
at rule #10.

So in this expression:

} 1:    $ foo="${(e)${array}[${top}, ${bottom}]}"

First ${array} expands, and then [$[top},${bottom}] applies to that
value -- which isn't an array, it's a string, so the subscripts are
extracting a range of characters from that string.  Finally that
substring is re-evaluated (but probably is nothing interesting).

Yes, by gum. Running diagnostics, there were several times when what was printed were just a few chars. I didn't even try to make sense of it.

I have no idea why you want to put yourself in that situation,

It seems unavoidable if I'm to use arrays to  pass values to functions.


    foo='\$${IN[list]}[${IN[topE]}, ${IN[bottomE]}]'
    IN[PAGE]="${(e)$(print -R "${(e)${foo}}")}"

... 'IN' is the array copied by value from whatever array holds the data for the particular window in play. So in the above, I'm setting the contents of the current displayed page to a range from within the entire available data which is stored in the array who's name is held in ' IN[list]' (and which varies depending on the window). It's called like this:

set -A IN ${(kv)main} # The window in play has all it's data in the array 'main'.
    n_list_draw 0 1

In the original, it's done like this:

        n-list-draw "$(( (NLIST_CURRENT_IDX-1) % page_height + 1 ))" \
"$page_height" "$page_width" 0 1 "$NLIST_TEXT_OFFSET" inner ansi \
            "${(@)col_list[NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN, end_idx]}"

... and of course there are all the local values in the function to receive the arguments, and at the end of the function all the changes have to recaptured to specific variables depending on the window.

Mine seems simpler, however I'm open to any suggestion. I quite understand that I'm pushing zsh past it's natural comfort zone, but it does seem to be working, it's readable and extendable, but there might be an entirely different and better way of going about it.
You can replace the $(...) with another ${(e)...} to get your third
needed re-evaluation, and you don't need the inermost ${ } around bar:

     foo="${(e)${(e)${(e)bar}}}"

Marvelous. It seems a bit of a labor, but it's understandable. Puts me in mind to ask why we can't have the 'expand everything in one go' flag:

     foo="$(E)bar}

Again it's pretty ridiculous that you're doing anything like this in
the first place.

As above, is there a better way? I confess again that I'm trying to make zsh into C, but I'm getting away with it. Why shouldn't structured programming be available in zsh?

}       $ foo='stranger'
}       $ bar='echo howdy $foo'
}       $ eval baz=$bar; echo $baz
}     zsh: command not found: howdy << Ferkrissakes

Well, think about it a bit harder.  Or better yet, "setopt xtrace" and
watch what is happening.

I understand what eval is doing, my point is just that it's hardly the safe thing when all I want to do is set a parameter from another parameter than contains parameters itself. Of course there are times when we want eval, but setting a parameter ain't it. (e) is it.

Thanks Bart, a superb explanation as always.



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