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

Re: More rabbit-holes with unset variables



2020-11-25 16:17:46 -0600, Felipe Contreras:
[...]
>   The variable whose name is specified shall be created as a local
> variable with name "name". It
>   shall inherit its initial value, as well as the exported and
> readonly flags, from the variable
>   with the same name in the surrounding dynamic scope if there is one;
> otherwise, the variable is
>   initially unset. Then, if "=word" is provided, the value of that
> local variable shall then be set
>   to word.
[...]

You'd describing the ash/bosh behaviour. Most other shells
behave differently. As mentioned at that SE Q&A or in that POSIX
issue, there is a strong case for that variable to be a brand
new variable with an initial unset or empty/0/empty-list value
depending on the type.

In reality, depending on the shell you get:

- variable left as is from the parent scope (inherit, value,
  type, attributes), but restored upon return of function.
  Useful in things like "local PATH" where you want to keep the
  current value of PATH, be able to do modifications and restore
  the original value upon return of the function.

  That approach is not acceptable for a shell with other types
  of variables (array, hash, compound) and with variable
  attributes (integer, float, padding, uppercase...). Because
  that would invalidate all the uses like:

  f() { local i; for i do ...; done; }

  Which would be broken if i remained a hash/integer/padded...

  In ash, that function doesn't work in contexts where i has
  been made read-only in a parent scope, and leaks the value of
  i to executed commands if it was exported. NetBSD sh added
  "local -N i" for that. Though you could also do
  "local var; unset var" (not portable as it doesn't work in
  mksh/yash)

- variable created unset but inheriting some of the attributes
  (bash) that's the worst of both world as you don't know what
  you're going to get. (localvar_unset doesn't address that).

- variable created anew initially unset

- variable created anew with initial value (zsh).

As to unset vs initial value, both have merits. While I'd tend
to prefer "initially unset", it makes sense that "local -i i;
echo "$i"" outputs an integer. Or that "local -Z2 v; echo $#v"
outputs 2.

In any case, I don't think zsh can change its default behaviour
as it would break backward compatibility.

It could add -N/-I à la NetBSD sh if people found it was useful
enough.

It could try and emulate ksh in ksh emulation, but which ksh?
ksh88, ksh93 and mksh behave radically differently in that
regard. Also few people use ksh these days, so I'm not sure it's
worth the effort. While the ksh emulation mode can help with
bash compatibility, bash's behaviour in this instent is also
very different.

-- 
Stephane




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