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

Re: PATCH: Icky little array slice assignment bug



On May 19,  5:13am, Wayne Davison wrote:
}
} > x y W x y z V		<-- this is ok
} > zagzig% a[(R)q]=U
} > zagzig% echo $a
} > U y W x y z V		<-- this is probably unexpected
} 
} This is because we currently have a[0] as an alias for a[1].  Did we
} have a good reason for that?

Aside from "it's behaved that way for 12 years so somebody might be
relying on it," I can't remember one.

However, it doesn't seem to be documented anywhere except Etc/FAQ, so
we might be able to get away with changing it.  We are having a major
version number change, after all.

} I think it would make more sense to have a[0] return an empty string,

(This of course causes several of the "make check" tests to fail.)

} while setting it should prepend an element to the array. My appended
} patch goes this route.

I note that with the patch applied, array[(R)non-element] produces the
empty string even when ksharrays is set, but array[(I)non-element] is 0,
which means that array[(R)non]=element and array[(I)non]=element behave
differently under ksharrays.  Of course, ksh doesn't support that syntax
at all, so this shouldn't bother anyone trying to run a real ksh script,
but it definitely warrants mention somewhere.

Put another way:  [[ $a[(R)p] == $a[a[(I)p]] ]] || explain why not.
 
} > zagzig% a=(a b c)
} > zagzig% a[2,(R)q]=x
} > zagzig% echo $a
} > a x a b c
} 
} Yeah, that's really non-intuitive, isn't it?  You actually told zsh that
} you wanted all elements before 2 ("a") before the new string, and all
} the elements after 0, ("a b c") after the string.

Hrm.  That's not a very Boolean way to interpret "and"; I thought I told
zsh that I wanted all those elements, where each has the properties of
being at-or-after 2 and (also) at-or-before 0, replaced by x.  There are
no such elements; zsh's normal response in that case is to create them,
but that's impossible as well (so we're free to define it as insert).

The thing is, I think that a[N,(R)p] should stop searching when it gets
to the Nth element.  Sort of the inverse of a[(Rb:N:)p].  Your patch does
make zsh behave as if this is the case, so that's good; actually stopping
the search early would just be an optimization.

} If we decide that changing a[0] is a bad idea, I can change $a[(R)q]
} to return an empty string when there is no match (rather than the first
} element of the array), and I could even make "a[(R)q]=prepend" work
} without affecting "a[0]=newfirstelement".

To see this in action, just apply the patch and setopt ksharrays.  I wish
I could think of a sensible workaround.  The only thing that comes to
mind is to parse a[-0] specially, and then have $a[(I)non] return "-0";
but that seems pretty odd.

There's one other oddity:  The argv array.

zagzig% set -- a b c
zagzig% echo $argv
a b c
zagzig% 0=x
zagzig% echo $argv
a b c
zagzig% argv[0]=x
zagzig% echo $argv
x a b c
zagzig% 3=(y z)
zagzig% echo $argv
x a y z c
zagzig% 0=(p q)
zsh: 0: attempt to assign array value to non-array
zagzig% setopt ksharrays
zagzig% echo ${argv[0]}
x

Arguably, indexing of argv should be 1-based even when ksharrays is set,
since $0 is not really part of the array, but that may be pretty hard to
accomplish.  In any case the positional parameters section of the manual
should explain about $0.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   



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