[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Changing the way bash expands associative array subscripts

From: Koichi Murase
Subject: Re: Changing the way bash expands associative array subscripts
Date: Wed, 14 Apr 2021 12:11:31 +0900

2021年4月14日(水) 0:24 Chet Ramey <chet.ramey@case.edu>:
> On 4/13/21 5:01 AM, Koichi Murase wrote:
> > But I expected some design consideration enabling a[$key] for an
> > arbitrary key in the indirect expansions and namerefs.
> Why? Why should the shell carry around (and expect the user to remember)
> information about the original value assigned to a variable pre-expansion?

I didn't mean we should preserve the syntactic information, which I
don't either think is a good idea.  Maybe we could always treat
`assoc[@]' as a single element reference.  Maybe there is another
better idea.  Maybe there is no good way, but I thought it's worth
taking some consideration. (But these discussions are all based on my
false assumption that indirect expansions and namerefs would be
changed not to undergo expansions on the reference time.)

> > If you are talking about the new behavior as I expect, why would
> > «iref='a[\@]'» work?
> Why would it not? The rationale for the change is to eliminate the double
> expansion of array indices that happens under certain circumstances, not
> eliminate expansion of array indices entirely.

I think now I understand the proposed change.  So, indirect expansions
and name references are not planned to be changed because it already
undergoes only a single set of expansions at reference time?

> > (a) Is it because indirect expansions and name references are not
> > planned to be modified this time (unlike `unset') and will still
> > require careful quoting of the key strings after the change?
> Do you think that array indices should not be expanded at all?

No, I don't think so.  I agree that the expansions should be performed once.

> Under what circumstances should they not be expanded? Because the
> indirect expansions of array subscripts still undergo a single set
> of word expansions.

>From the users' point of view, indirect expansions and name references
currently undergo "double expansions" in assigning time and in
reference time; I mean naive users will write as « iref=a[$key] »
instead of « iref='a[$key]' » and run « echo "${!iref}" » to find that
the original right-hand side of the assignment is finally
double-expanded until the reference time.

But, at the same time, I think it is also a valid discussion that we
want to keep « ${!iref} » and « eval "\${$iref}" » equivalent to each
other.  There is no perfect solution.  If one takes a rational
semantics, I think the current behavior of ${!iref} should be kept.
If one takes the semantics that naive users won't be surprised, I
think the subscripts shouldn't be expanded at the reference time.  In
any way, I would like to see consistency with « ref=a[$key]; unset
"$ref" ».  If one takes the rational semantics, I believe the `unset'
builtin should expand the array subscripts by itself so that « unset
'a[$key]' » works (as with the current default, shopt -u
assoc_expand_once).  If one takes the semantics that is friendly to
naive users, the `unset' builtin can stop its own expansion (shopt -s

I actually agree with konsolebox that assoc_expand_once for unset
shouldn't be defaulted.  The option `assoc_expand_once' is incomplete
in the sense that the behavior of `a[@]' and `a[*]' are subtle.  I see
the current default behavior (with `assoc_expand_once' turned off)
more consistent and clean.  It seems to me that the option
`assoc_expand_once' is just for naive users who fail to properly quote
the arguments of `unset' but is inconsistent and ambiguous.  I even
think the effect of `assoc_expand_once' on `unset' could be removed,
and we can tell users to always write « unset 'a[$key]' », «
iref='a[$key]'; echo "${!iref}" » and « declare -n nref='a[$key]';
echo "$nref" ».

> > I thought the purpose of the planned change of the associative array
> > subscripts is to solve the inconsistency between the usages of ((
> > a[\$key] )), unset 'a[$key]', etc. and the usages of a[$key]=xxx,
> > ${a[$key]} so that we can write (( a[$key] )), unset "a[$key]",
> > iref=a[$key], declare -n nref=a[$key], etc.
> The purpose of the change is as I wrote above, and as I wrote originally:
> "basically force the equivalent of `assoc_expand_once' on all the
> time, with additional changes to prevent unwanted double expansion in an
> arithmetic expression context."

I completely agree on the change on the arithmetic expression ((
assoc[$key] )).  I don't like the behavior of `unset' under
`assoc_expand_once' because it seems be inconsistent to me, but there
may be different perspective.  But, If `assoc_expand_once' is needed
to make the behavior more friendly to naive users, I think we should
also take care of naive users who write « iref='a[$key]'; echo
${!iref} ».


reply via email to

[Prev in Thread] Current Thread [Next in Thread]