0

I'm trying to define a zsh function in a batch, using a for loop. I would expect to get different functions, e.g. pre1post, pre2post etc., each of which referring to the value of the variable at the moment of function creation.

From what I tried, I get the name of the function correctly but the value used in the loop refers to the last value in the array (as if it was a global variable?).

How can I save the current value of the variable in each defined function?

DESCRIPTORS=("1" "2" "3")

for i in $DESCRIPTORS; do
    function "pre"$i"post"() {
        echo i=$i

        local j=$i
        echo j=$j

        eval "k=$i; echo k=$k"
        echo p=${(P)ENV_DESCR}

        eval "value=\"\${$ENV_DESCR}\""
        echo v="$value"

    }
done;

> pre1post
i=3
j=3
k=
p=
v=
Sebastian Kramer
  • 689
  • 1
  • 9
  • 18

2 Answers2

1

References to i in the body are evaluated when your function is called, not when it is defined. zsh does not provide closures. See Is there something like closures for zsh? for more information.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

You can use the substitution modifier to extract the number from the function name, like ${0:s/pre//:s/post//}.

$0, and therefore ${0}, refers to the function name, for example "pre1post". The modifier s/l/r/ generally replaces "l" with "r", or in our case s/pre// replaces "pre" with nothing. We can apply multiple modifiers by separating them with colons in order to make multiple of such subsitutions:

0=pre1post echo ${0:s/pre//:s/post//} # outputs 1

Another way would be to use ${0:3:-4} and work with offsets. :3:-4 means to skip the first 3 and the last 4 characters, referring to the length of "pre" and "post":

0=pre1post echo ${0:3:-4} # outputs 1
Teele
  • 51
  • 5