Re: Changing the way bash expands associative array subscripts

2021-04-12 Thread Chet Ramey

On 4/6/21 12:46 PM, Koichi Murase wrote:


How about the cases with `test -v a[@]' and `key=@; test -v a[$key]'?


By the time test sees its arguments, there is no difference between these
two cases. You can do things to differentiate when running the `[['
command, but `test' goes through the entire set of word expansions.



I remember there was some discussion in the bug-bash list on the
behavior of `test -v a[@]' which actually tests whether the array `a'
has at least one element. It cannot be replaced by `test -v a' because
`a' implies `a[0]' here. But if I correctly understand it, `test -v
a[@]' can be replaced by `((${#a[@]}))'. Should any scripts relying on
`test -v a[@]' to test the array elements also be changed?


I'm ok with making the old behavior contingent on a compatibility setting,
like with `unset'.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: Changing the way bash expands associative array subscripts

2021-04-12 Thread Chet Ramey

On 4/6/21 12:46 PM, Koichi Murase wrote:


Looking at another thread
https://lists.gnu.org/archive/html/bug-bash/2021-04/threads.html#00051,
I'm now also interested in how we can handle the indirect expansions
for 'a[@]' and the namerefs for 'a[@]':

$ declare -A a=(['@']=x [1]=y)
$
$ # indirect expansions
$ iref1=a[@]; printf '<%s>' "${!iref1}"; echo

$ key=@; iref2=a[$key]; printf '<%s>' "${!iref2}"; echo
# <-- unexpected


But these cases are identical. After the assignment statement, iref2 has
value 'a[@]', just like iref1. I don't see why one would be more unexpected
than the other, and they're both equivalent to ${a[@]}. Unless that's your
point?



$ # namrefs
$ declare -n nref1=a[@]; printf '<%s>' "$nref1"; echo

$ key=@; declare -n nref2=a[$key]; printf '<%s>' "$nref2"; echo
# <-- unexpected


Yes, namerefs are different, but not in a way that matters here. These two
cases are identical as well. If you added `declare -p nref2', you'd see it.
(The differing output issue got fixed back in January, the result of
https://lists.gnu.org/archive/html/bug-bash/2021-01/msg00148.html)

I guess I see what your point might be, but these aren't different cases.
Variables don't carry around the kind of state that might be used to
differentiate their behavior depending on the value they got at assignment
time. There is no useful syntactic information there.

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: Changing the way bash expands associative array subscripts

2021-04-12 Thread Chet Ramey

On 4/9/21 12:20 PM, Koichi Murase wrote:


That said, the fact that you can put 'a[@]' in an indirect variable and
get an array expansion out of "${!x}" is completely repulsive to me.


Currently, we need to write as «iref='a[$key]'; echo "${!iref}"» so
that $key is not expanded until the referencing (just like «unset
'a[$key]'»). If the new assoc_expand_once enables the indirect
expansions of the form «iref="d[$key]"; echo "${!iref}"» like «unset
"a[$key]"» and also if we don't change the current behavior of
«iref=a[@]; echo "${!iref}"» (being expanded to all the elements of
the array) as Greg's suggestion, we need to work around the case key=@
for «iref="d[$key]"; echo "${!iref}"». However, it seems to me that
there is no workaround. What string should we assign to `iref' to
create a reference to the element associated with key=@ with Greg's
suggestion?


Ah, ok. I see. You can assign '\@' to iref to get the behavior you want.
It's not perfect, but it's possible:

$ cat x6b
shopt -s assoc_expand_once
declare -A a=(['@']=x [1]=y)

printf '<%s>' "${a[@]}"; echo

printf '<%s>' "${a[\@]}"; echo

iref1='a[\@]'
echo "$iref1"
printf '<%s>' "${!iref1}"; echo

key='\@'; iref2=a[$key]
echo "$iref2"

printf '<%s>' "${!iref2}" ; echo
$ ./bash ./x6b


a[\@]

a[\@]



Once you choose to have ${a[@]} expand to all the elements of an array,
whether it's indexed or associative -- and that choice came years ago --
using that character as a key is always going to require a workaround.
Some of them won't be pretty.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/