I don't recall all the details (again, other readers?) but my
recollection is that there's a POSIXy issue here. E.g., an exported
parameter remains exported even if unset (so re-assigning it updates
the environment), and I believe numeric types are supposed to retain
their properties across unset. This is why I wonder whether
references ought also to retain reference-ness across unset.
I always considered it a bug that references remain references across unset because in Zsh only local references exhibit this behavior (not global ones) and no other type (integer, float, array, ...) is retained across unset. I have now confirmed that no type is retained across unset neither in ksh, nor in bash. See details below. Given all that, I think that
workers/54236 is correct.
Regarding exported parameters, references can't be exported; "typeset -n -x ref=var" raises an error. Therefore, I don't think we need to look at what happens with exported parameters. That being said, even with exported parameters I couldn't find a case where a type is retained across unset.
Below are functions and their output that I have used to confirm that no types are retained across unset. In each output, I have highlighted in red the result of "typeset -p ..." after the parameters were resurrected.
Zsh
The following function allows to test all parameter types for local (zsh-test-unset), global (G=-g zsh-test-unset), exported global (G=-g X=-x zsh-test-unset) and exported local (G=+g X=-x zsh-test-unset) parameters:
zsh-test-unset() {
typeset $G $X s=foo
typeset $G $X -i i=42
typeset $G $X -E E=4.2
typeset $G $X -F F=4.2
typeset $G $X -a a=(foo1 foo2)
typeset $G $X -A A=([fooK]=fooV)
typeset $G -n n=foo
PS4="# "; set -x
typeset -p s i E F a A n
unset -n s i E F a A n
typeset -p s i E F a A n
typeset $G s i E F a A n
typeset -p s i E F a A n
}
Here is the output for local parameters:
$ zsh-test-unset
# typeset -p s i E F a A n
# typeset -p s i E F a A n
typeset s=foo
typeset -i i=42
typeset -E E=4.200000000e+00
typeset -F F=4.2000000000
typeset -a a=( foo1 foo2 )
typeset -A A=( [fooK]=fooV )
typeset -n n=foo
# unset -n s i E F a A n
# typeset -p s i E F a A n
# typeset s i E F a A n
n=''
# typeset -p s i E F a A n
typeset s=''
typeset i=''
typeset E=''
typeset F=''
typeset a=''
typeset A=''
typeset -n n=''
Only the reference type is retained across unset.
Ksh (Version AJM 93u+m/1.0.10 2024-08-01)
Here is a similar function for ksh. Note that with ksh, "typeset var" doesn't create/resurrect any parameter; a type and/or a value has to be provided to trigger the creation/resurrection of a parameter.
function ksh_test_unset {
typeset $G $X s=foo
typeset $G $X -i i=42
typeset $G $X -E E=4.2
typeset $G $X -F F=4.2
typeset $G $X -a a=(foo1 foo2)
typeset $G $X -A A=([fooK]=fooV)
typeset $G -n n=foo
PS4="# "; set -x
typeset -p s i E F a A n
unset -n s i E F a A n
typeset -p s i E F a A n
typeset $G s i E F a A n
typeset -p s i E F a A n
typeset $G s=bar i=bar E=bar F=bar a=bar A=bar n=bar
typeset -p s i E F a A n
}
Here is the output for local parameters:
$ ksh_test_unset
# typeset -p s i E F a A n
s=foo
typeset -i i=42
typeset -E E=4.2
typeset -F F=4.2000000000
typeset -a a=(foo1 foo2)
typeset -A A=([fooK]=fooV)
typeset -n n=foo
# unset -n s i E F a A n
# typeset -p s i E F a A n
# typeset s i E F a A n
# typeset -p s i E F a A n
# s=bar
# i=bar
# E=bar
# F=bar
# a=bar
# A=bar
# n=bar
# typeset s i E F a A n
# typeset -p s i E F a A n
s=bar
i=bar
E=bar
F=bar
a=bar
A=bar
n=bar
No type is retained across unset.
Bash (5.2.21(1)-release)
Here is the function for bash, which doesn't have support for float parameters:
bash-test-unset() {
typeset $G $X s=foo
typeset $G $X -i i=42
typeset $G $X -a a=(foo1 foo2)
typeset $G $X -A A=([fooK]=fooV)
typeset $G $X -n n=foo
PS4="# "; set -x
typeset -p s i a A n
unset s i a A
unset -n n
typeset -p s i a A n
typeset $G s i a A n
typeset -p s i a A n
}
Here is the output for local parameters:
$ bash-test-unset
# typeset -p s i a A n
declare -- s="foo"
declare -i i="42"
declare -a a=([0]="foo1" [1]="foo2")
declare -A A=([fooK]="fooV" )
declare -n n="foo"
# unset s i a A
# unset -n n
# typeset -p s i a A n
declare -- s
declare -- i
declare -- a
declare -- A
declare -- n
# typeset s i a A n
# typeset -p s i a A n
declare -- s
declare -- i
declare -- a
declare -- A
declare -- n
No type is retained across unset.
Philippe