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

Re: "typeset -p" inconsistency



On Tue, Nov 1, 2022 at 5:40 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
>
> On 2022-10-31 22:00, Bart Schaefer wrote:
> > On Thu, Oct 20, 2022 at 7:25 PM, I wrote:
> >>> typeset -T CDPATH cdpath=(  )
> >>> typeset -aT CDPATH cdpath=(  )
> >> The first one is the (incorrect) assignment for $CDPATH.
> > Nobody called me out on that ... the first assignment is actually just
> > fine.
>
> But the 'typeset - g -aT ... ' remains a bug as you said?  Or at least a
> redundancy?

That's not what I said, in either case.  Again, the -g appears only
when, from inside a function, you ask typeset (by passing the -p
option) to display a command that would create a variable that
persists (is global, hence -g) after the function returns.

The two examples above aren't really "redundant" either.  You asked
typeset to display commands to re-create all the current variables.
The first command is meant to re-create the scalar CDPATH and the
second is meant to re-create the array cdpath.  Because they could
have different attributes (the -U example you trimmed), it's not
redundant to output each of them separately.

The "buglet" is that if you execute both assignments, you end up
assigning all the attributes of either one of the pair to both of the
pair:

% typeset -UT FOO foo=(a b c b a)
% typeset -p foo
typeset -aUT FOO foo=( a b c )
% typeset -p FOO
typeset -UT FOO foo=( a b c )

Both have -U.  Now add -u to just the array:

% typeset -u foo
% typeset -p FOO
typeset -UT FOO foo=( a b c )
% typeset -p foo
typeset -auUT FOO foo=( a b c )

The output is different for each, as it should be ... but if I execute
that first one:

% typeset -auUT FOO foo=( a b c )
% typeset -p FOO
typeset -uUT FOO foo=( a b c )

Oops, we've added -u to FOO as well.  This is an inevitable ambiguity
in the syntax for creating tied variables.

One way to resolve it may be to separate the declaration of tied-ness
from the declaration of other attributes, as PWS mentioned, although I
think there's still ambiguity with respect to in which order the
declarations and the assignments must appear:

% typeset -u FOO
% typeset -T FOO foo=(a b c)
% typeset -p FOO
typeset -T FOO foo=( a b c )

Note -u has been lost from FOO by the subsequent -T declaration.  This
means we can't get away with outputting the assignments for each
variable as we encounter it in the hash table scan, but I'm also not
sure it's sufficient to first scan for and emit all the -T and then
emit all the attribute settings.

There's a comment in the code:

            * We choose to print the value for the array instead of the scalar
            * as scalars can't disambiguate between
            * typeset -T SCALAR array=()
            * and
            * typeset -T SCALAR array=('')

This is an impossible situation for assignment whenever there are
attributes of the scalar that are not in common with the array.

One possibility (which would be a backwards-incompatible change) would
be to treat

typeset -a ... -T FOO foo

as applying all flags to only the array, and

typeset ... -T FOO foo

(without -a) as applying all flags only to the scalar.  That doesn't
fix the assignment problem, though.  Another possibility would be to
allow attribute flags to appear between the scalar name and the array
name, something like:

typeset <attributes for both> -T <attributes for scalar> FOO
<attributes for array> foo

but that breaks the use of our generic option parsing code and still
doesn't solve the assignment ambiguity.




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