Re: zsh style associative array assignment bug
28 Mart 2021 Pazar tarihinde Eric Cook yazdı: > > 1) For consistency sake with the shell the idea was borrowed from mostly. That an idea was borrowed from another shell doesn't mean it should be implemented the same kludgy way. Besides, bash doesn't offer compatibility with zsh. > 2) Prior to this extension bash required specifying the key and value for > AA assignments, so it seems weird to silently ignore that a value wasn't > given now. The oldest version of Bash I ever used is 4.4.20, and if my memory serves me right, it didn't regard omission of a value inside a compound assignment (like `foo=([bar]=)`) an error. If otherwise and it actually did, that was a mistake. > 2.5) I subjectively think passing an odd number of elements to declare is > more often > than not to be a mistake that the user would be interested in knowing > about. > > With the way it is now, you could save a few characters to do a seen array. > $ while read -r key; ... seen+=("$key") ... > but not really much else. I believe bash will eventually (if hasn't already done in devel) allow `$@' and the like to expand to multiple words inside a compound assignment to an associative array. Being forced to trim an array to an even number of elements before using it inside such an assignment would be really annoying, in my opinion. -- Oğuz
Re: zsh style associative array assignment bug
On Sun, Mar 28, 2021 at 10:16 AM Oğuz wrote: > That an idea was borrowed from another shell doesn't mean it should be > implemented the same kludgy way. Besides, bash doesn't offer compatibility > with zsh. > You don't think the realm of POSIX-ish shells already has enough incompatibilities and minor quirks between the different shells? :) The oldest version of Bash I ever used is 4.4.20, and if my memory serves > me right, it didn't regard omission of a value inside a compound assignment > (like `foo=([bar]=)`) an error. If otherwise and it actually did, that was > a mistake. > But this is an error: a=([foo]=123 [bar]) Now, the syntax is different so it's not a fair comparison, really. But spinning up an empty word where none exists is not something the shell usually does anywhere else, so why should it do that here? I believe bash will eventually (if hasn't already done in devel) allow `$@' > and the like to expand to multiple words inside a compound assignment to an > associative array. Being forced to trim an array to an even number of > elements before using it inside such an assignment would be really > annoying, in my opinion. > I wonder, what would the use case be? I could understand assigning the words from "$@" to the keys of an associative array might be useful, but where would you want to fill the keys and values, while at the same time silently allowing a missing value? Or silently dropping one. Shouldn't a script treat that as an error and have the user recheck what they're doing, the same as in any case where a tool gets too many or too few arguments?
Re: zsh style associative array assignment bug
28 Mart 2021 Pazar tarihinde Ilkka Virta yazdı: > On Sun, Mar 28, 2021 at 10:16 AM Oğuz wrote: > >> That an idea was borrowed from another shell doesn't mean it should be >> implemented the same kludgy way. Besides, bash doesn't offer compatibility >> with zsh. >> > > You don't think the realm of POSIX-ish shells already has enough > incompatibilities > and minor quirks between the different shells? :) > > The oldest version of Bash I ever used is 4.4.20, and if my memory serves >> me right, it didn't regard omission of a value inside a compound >> assignment >> (like `foo=([bar]=)`) an error. If otherwise and it actually did, that was >> a mistake. >> > > But this is an error: > >a=([foo]=123 [bar]) > As it should be. `[bar]' doesn't qualify as an assignment without an equals sign, the shell thinks you're mixing two forms of associative array assignment there. In the new form, that a key is listed inside a compound assignment alone implies that it was meant to be assigned a value. In my mind, `a=(foo 123 bar)' translates to `a=([foo]=123 [bar]=)'. It makes sense. > > Now, the syntax is different so it's not a fair comparison, really. But > spinning up an > empty word where none exists is not something the shell usually does > anywhere > else, so why should it do that here? > Pairing separate words for further processing is not something the shell usually does anywhere else either. So why shouldn't it? > I believe bash will eventually (if hasn't already done in devel) allow `$@' >> and the like to expand to multiple words inside a compound assignment to >> an >> associative array. Being forced to trim an array to an even number of >> elements before using it inside such an assignment would be really >> annoying, in my opinion. >> > > I wonder, what would the use case be? I could understand assigning the > words > from "$@" to the keys of an associative array might be useful, but where > would > you want to fill the keys and values, while at the same time silently > allowing a > missing value? Or silently dropping one. Shouldn't a script treat that as > an error > and have the user recheck what they're doing, the same as in any case where > a tool gets too many or too few arguments? > The shell already allows missing values in assignments, `a=' is not an error. -- Oğuz
Re: zsh style associative array assignment bug
On 3/28/21 7:02 AM, Oğuz wrote: As it should be. `[bar]' doesn't qualify as an assignment without an equals sign, the shell thinks you're mixing two forms of associative array assignment there. In the new form, that a key is listed inside a compound assignment alone implies that it was meant to be assigned a value. In my mind, `a=(foo 123 bar)' translates to `a=([foo]=123 [bar]=)'. It makes sense. That is the point that i am making, in typeset -A ary=([key]=) an explicit empty string is the value, but in the case of typeset -A ary=([key]) it was historically an error. So why should an key without a value now be acceptable?
Re: zsh style associative array assignment bug
On Sun, Mar 28, 2021 at 9:02 PM Eric Cook wrote: > in typeset -A ary=([key]=) an explicit empty string is the value No. An "explicit" empty string would be '', "", or something like that. After `=' a value is expected but it's not there, so `[key]' is assigned the empty string. `typeset -A ary=(key)' is similar, the value is not there and the empty string is taken as the value instead. but in the case of typeset -A ary=([key]) it was historically an error > Irrelevant. See above
Re: zsh style associative array assignment bug
Date:Sun, 28 Mar 2021 22:01:14 +0300 From:=?UTF-8?B?T8SfdXo=?= Message-ID: | No. An "explicit" empty string would be '', "", or something like that. No, not in sh it isn't - all quotes do is hide the effects of special characters (and prevent some uses, eg: as a reserved word). There are no "string" (enclosed in quotes) data types in sh, a and 'a' and "a" and \a are all the exact same thing. That applies to empty values too, the only difference is that there needs to be some reason to believe that the empty value exists, rather than is not present at all. | After `=' a value is expected but it's not there It is there. It is just empty. How this applies to associative array init's I neither know nor care. kre
Re: zsh style associative array assignment bug
On Sun, Mar 28, 2021 at 10:01:14PM +0300, Oğuz wrote: > On Sun, Mar 28, 2021 at 9:02 PM Eric Cook wrote: > > > in typeset -A ary=([key]=) an explicit empty string is the value > > No. An "explicit" empty string would be '', "", or something like that. > After `=' a value is expected but it's not there, so `[key]' is assigned > the empty string. Consider this assignment command: x= It's syntactically valid, and it assigns the empty string to the variable x. It's perfectly reasonable, therefore, for a=([key]=) to assign the empty string to a[key]. You don't need '' or "" or whatever. Now, as far as hash=(a b c) goes, I don't have a strong opinion about it. Some of the other languages that have such a feature treat it as an error. We've already heard from zsh. Here's Tcl: % array set hash {a b c} list must have an even number of elements Perl does what bash does, kinda: unicorn:~$ perl -e 'use Data::Dumper; %hash=qw(a b c); print Dumper(\%hash);' $VAR1 = { 'a' => 'b', 'c' => undef }; Python is different: >>> y = ["a", "b", "c", "d"] >>> dict(zip(y[::2], y[1::2])) {'a': 'b', 'c': 'd'} >>> x = ["a", "b", "c"] >>> dict(zip(x[::2], x[1::2])) {'a': 'b'} It seems to discard the last (unmatched) value. Also, dear gods, what is that horrible syntax they forced me to google for... and it took MANY tries to find it, too. So, that's 2 votes for error, 2 votes for using the empty string (or null/undef) as the last value, and 1 vote for silently dropping the last key. Definitely not a consensus.