help-bash
[Top][All Lists]
Advanced

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

Re: [Help-bash] Awkward behavior of empty arrays


From: Andy Chu
Subject: Re: [Help-bash] Awkward behavior of empty arrays
Date: Thu, 31 Aug 2017 09:16:46 -0700

On Thu, Aug 31, 2017 at 7:47 AM, Chet Ramey <address@hidden> wrote:

>
> > 1. Never use anything that isn't in parentheses on the RHS of an array
> > initialization.
>
> This is essentially an attempt to avoid the implicit use of subscript 0.
>


Yes I'm suggesting a style where all implicit conversions are avoided (from
the POV of someone coming from another programming language).  If you can
see a case where implicit conversions happen using the rules I gave, that's
a bug :)

As I just wrote, avoiding

declare -a A=x

in favor of:

declare -a A=(x)

is analogous to avoiding "$A" in favor of "{$A[0]}".



>
>
> > "${A[*]}"
> > ${A[*]}
> These are useful in the same way that $* and "$*" are useful.
>

I actually never use $* "$*" $@, or ${A[*]} "${A[*]}" address@hidden in any of 
my
programs.  I believe they can always be expressed using different (IMO
clearer) mechanisms.

Consider this:

$ set -- foo '*.sh' bar

There are only 3 possibilities from the four constructs (AFAICT $* is
identical to $@):

$ argv "$@"
['foo', '*.sh', 'bar']

$ argv $@
['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']

$ argv "$*"
['foo *.sh bar']

$ argv
$*

['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']

These 3 possibilities can always be achieved as follows:

$ argv "$@"
['foo', '*.sh', 'bar']

$ joined="$@"  # explicit join

$ argv "$joined"
['foo *.sh bar']

$ argv $joined
['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']

So I have used nothing but "$@" to generate all 3 possibilities.  Similarly
for "address@hidden".



>
>
> > In particular, don't expect to compare arrays with [[.
> >
> > $ declare -a A=(A B C D)
> > $ declare -a B=('A B' 'C D')
> >
> > $ echo "address@hidden"
> > 4
> > $ echo "address@hidden"
> > 2
> >
> > # arrays compare equal because they're coerced to strings before
> comparison
> > $ [[ "address@hidden" == "address@hidden" ]]; echo $?
> > 0
>
> Because the operands in [[ commands don't undergo word splitting.
>

Yes, it depends how you think about it from the implementation POV.  In
OSH, variables are represented by a discriminated union (in ML-like syntax):

value =
    Undef
  | Str(string s)
  | StrArray(string* strs)

So when I do [[ "address@hidden" == "address@hidden" ]], I actually have to 
JOIN the
arrays first to main compatibility with bash (there could be a flag to turn
this off.)

So it's not just lack of splitting, but ADDING joining (i.e. coerce an
array to string).  But if bash stores arrays as FLAT strings internally,
and only does splitting upon splicing into an argv array, then you can
think of it as lack of splitting.

Andy


reply via email to

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