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

Re: Zsh's and ksh's bang (!) expansion flags have different meanings



My previous message contains two patches:

- Patch 1: Reverts Zsh's emulation of ksh's ${!var} from ${(!k)var} to ${(k)var}
- Patch 2: Extends ${(k)var} in ksh emulation to be active in more cases

In ksh the ! in ${!var} is always active; ${!var} always expands to something different than ${var}. Things are different in Zsh. Both the (!) in ${(!)var} and the (k) in ${(k)var} are only active in some cases. For instance, ${(!)var} expands to the same as ${var} if var isn't a named reference and ${(k)var} expands to the same as ${var} if var is neither an array nor a hashtable.

My rationale against mapping ${!var} to ${(!k)var} and in favor of patch 1 is that when (!k) in ${(!k)var} and (k) in ${(k)var} are active, there are about the same number of cases (but different ones), where they return the expected result (or a similar one) but there are many cases where (!k) is active and returns a bogus result while there are very few (or none, depending on what you count) for (k). I see (!k) as a dead end because it bakes in many bogus results, while (k) can be extended to become active in more cases to return the expected result.

The table below shows in green cases where the result is the same as in ksh, in orange, cases where it's similar, in blue, cases where ! has no effect and in pink cases where ! is active but returns a bogus result. We can disregard the lines for !arr[1,2] and !str[1,2] because ksh doesn't support multiple subscripts. Let's also ignore cases of chains of references (the third value in each triplet), which surely will be less common than plain variables and plain references. Then, there are only 6 cases where (!k) is active and matches ksh (or returns something similar), the same as for (k), but there are 6 cases where (!k) is active and returns a bogus result while there are none for (k). My patch 2 shows that it's possible to extend (k) such that it's active and correct in 6 more cases and still never actively bogus. Note also that the extended (k) is strictly better than (!k).

Obviously we could debate how to count cases but there is no denying that (!k) bakes in bogus results while (k) can be extended to become strictly better than (!k).


Zsh's ksh emulation

ksh

Zsh's ksh emulation

Zsh's ksh emulation


${!var} <=> ${(!k)var}


${!var} <=> ${(k)var}

${!var} <=> ${(k)var}

+ extend (k) in ksh emulation

!str

!str[1]

!str[1,2]

!str[@]


!arr

!arr[1]

!arr[1,2]

!arr[@]


!hsh

!hsh[1]

!hsh[@]

abc - str0 - str1

b - t - t

bc - tr - tr

abc - str0 - str1


aa - arr0 - arr1

1 - r - r

<error> - rr - rr

aa bb cc - arr0 - arr1


aa - hsh0 - hsh1

1 - s - s

0 1 2 - hsh0 - hsh1

str0 - str0 - str0

str0[1] - str1[1] - str2[1]

str0[1,2] - str1[1,2] - str2[1,2]

0 - 0 - 0


arr0 - arr0 - arr0

arr0[1] - arr0[1] - arr0[1]

arr0[2] - arr0[2] - arr0[2]

0 1 2 - 0 1 2 - 0 1 2


hsh0 - hsh0 - hsh0

hsh0[1] - hsh0[1] - hsh0[1]

0 1 2 - 0 1 2 - 0 1 2

abc - abc - abc

b - b - b

bc - bc - bc

abc - abc - abc


aa - aa - aa

1 - 1 - 1

<error> - <error> - <error>

aa bb cc - aa bb cc - aa bb cc


aa - aa - aa

1 - 1 - 1

0 1 2 - 0 1 2 - 0 1 2

str0 - str0 - str0

b - b - b

bc - bc - bc

abc - abc - abc


arr0 - arr0 - arr0

1 - 1 - 1

<error> - <error> - <error>

aa bb cc - aa bb cc - aa bb cc


hsh0 - hsh0 - hsh0

1 - 1 - 1

0 1 2 - 0 1 2 - 0 1 2

!var

!var

!var

!var

abc: result is the same as ${!var} in ksh

abc: result is similar to ${!var} in ksh

abc: result is the same as ${var}, i.e., the flag had no effect

abc: result is bogus, neither the same as ${!var} in ksh nor as ${var}, i.e., the flag was actively detrimental


Philippe



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