list slicing and splicing
Ka-Ping Yee
ping@lfw.org
Thu, 15 Oct 1998 01:37:11 -0700 (PDT)
I am asynchronously responding to issues individually
while others are still being processed. (Mark, i haven't
forgotten about the class/type-naming style convention;
it just needs more thinking.)
> >... I would like you to consider the sugar
> >methods "getslice" and "putslice" -- they make a nice parallel
> >to "get" and "put", and if expanded from [x:y] notation in the
> >language grammar would be really useful.
>
> First of all, in E, "x:y" expands to
>
> uriGetters["x"]["y"]
Rrrmr.
When i first saw uriGetter[] i read uriGeller[] and did
a double-take. :)
*sigh* I have been slightly uncomfortable about the idea
of allowing bare URLs in the language for a little while. I do
think it is extremely cool to have some support for accessing URLs...
but have you considered what happens when the URL is, say,
http://site.com/go.cgi?words=one%2ftwo+three&area=all#anchor
^ ^ ^ ^ ^ ^
comment? suchthat? operators? slot? comment?
Note that RFC1738 also permits ; : @ $ ! * ' ( ) ,
Luckily { } \ are outlawed.
The parentheses may confuse editors; the apostrophe may confuse
font-lock; the comma will require that you put a space after
a URL if you want to use it as an argument, e.g.:
getLinks(http://www.erights.org/)
getAttribute(http://www.erights.org/, "author")
will necessarily be syntax errors, while
getLinks(http://foo.com/la(la, )
getAttribute(http://foo.com/la(la, , "author")
would be valid.
If you see this as undesirable, options may include:
1. Bracket URLs with something distinctive. The obvious
and generally-used choice is <>, but i know you don't
like those. (Well, maybe requiring "<protocol:...>"
would make <> more palatable.)
2. Modify URL syntax to require escaping of characters
you don't like, i.e. insist that in E scripts people
use %2c %28 %29 instead of , ( ) respectively. This
solves the problem but breaks complete compliance with
RFC 1738; this may not matter since these characters
are relatively rare.
Well, not entirely. "#" will always appear before a
fragment identifier, and *must not* be escaped (or it
would be indistinguishable from the URL path). And
the Java people have graciously made javadoc generate
anchors of the form "...List.html#remove(int)".
3. Punt, enter URLs as strings, use some other object call
or syntactic sugar to indicate that you want to fetch
them or uriGet them or what have you. This would hurt
a little since it hides the *coolness* of having URLs
directly in the language.
There may be other possibilities i haven't thought of.
What did you have in mind that non-fetchable URLs like
mailto:markm@erights.org would yield?
And if file:/tmp/foo.txt gets you a read capability on a
file, how do you write, append to, or create new files?
> >I just like Python's slice notation a lot because it can express
> >a lot of list-manipulation ideas -- append, insert, slice, delete,
> >replace -- with one consistent orthogonal notation. Perl tries
> >to subsume many of these under "splice", but quite clumsily so.
>
> Might it be illuminating to tell us about Perl's "splice"?
Well, okay. They all assume mutability (which is another huge
problem in Perl), but anyway:
splice(@array, 3)
removes everything after the third element in @array.
splice(@array, 3, 2)
removes the elements $array[3] and $array[4], and everything
after that moves up to fill the hole.
splice(@array, 3, 2, (99, 98, 97))
substitutes the three elements 99, 98, 97 in place of the
elements that were at @array[3..4], shifting the remaining
elements over one spot.
splice() then returns whatever it removed. Thus:
Python: Perl:
------- -----
list[3] = 4 $list[3] = 4
list[3:5] = [1,2,3] splice(@list, 3, 2, (1,2,3))
list[:0] = [4,5,6] splice(@list, 0, 0, (4,5,6))
OR
@list = (4,5,6,@list)
list[:2] @list[0..1]
list[3:] @list[3..$#list]
list.append(4) push(@list, 4)
last = list[-1]; \ $last = pop(@list)
list[-1:] = []
chunk = list[2:5]; \ $chunk = splice(@list, 2, 3)
list[2:5] = []
head = list[0]; \ $head = shift(@list)
list[:1] = [] OR
$head = splice(@list, 0, 1)
There was once talk of a pop() method for lists in Python
that would make it slightly prettier to use lists as stacks.
The push()/pop() idiom in Perl does get used really often, and
push()/shift() for queues is used a lot too. You might consider
pop() as a reasonable inverse to append(). Not something i
would die for, but it is sometimes handy and reads nicely.
Having stacks and queues so trivial to use in Perl is probably
one of Perl's strengths, as people don't think twice about
using them casually all over the place. Hmm... if you chose
the remove(int) as opposed to the remove(Object) method as
the one-arg remove, and if negative indices are supported,
then i suppose remove(0) and remove(-1) would do for shift()
and pop() respectively.
> >Because Python's slices don't complain on out-of-bounds indices,
> >they make it really convenient for me to just check things without
> >getting paranoid about catching exceptions:
> >
> > if word[:1] == "a": # does this (possibly empty) word start with 'a'?
>
> I don't get it. What does "word[:1]" evaluate to if "word" is empty?
The empty string. The result of getting a slice that extends
out of bounds in Python is simply to clip the slice at the
bounds and return whatever can be gotten.
list = [1,2,3,4,5]
list[:3] -> [1,2,3]
list[3:8] -> [4,5]
> For such cases, I believe thrown exception are your friend.
The forgiving behaviour does come in handy sometimes, but your
reasoning is sound. I don't know what Guido's original motivation
was to decide to make slices forgiving. (But then again, by the
way, i don't recall anyone ever complaining that they weren't
more strict.)
> I'd like E's Strings and Tuples to eventually be Ropes.
They sound pretty cool. Too bad the paper isn't around...
maybe i can sneak into PARC's library and find it one of these days.
(Technically, i may still be a "no-fee consultant" there.)
> So, if there was a syntactically nice way to ask "give me a new
> Tuple like this Tuple but in which this subrange is replaced by
> this Tuple", would you still want the side effecty version?
Maybe not, if i knew that it was a truly cheap operation.
Hmm.
t := [1, 2, 5, 6, 8]
# value: [1, 2, 5, 6, 8]
t edit(3, 4, [0, 9, 1]) # or "t subst(...)"
# value: [1, 2, 5, 0, 9, 1, 8]
!ping