Permalink

A slice of Nice

17 AUG 2004

I've just committed slice support and a few other new features to the Nice CVS repository, and I'd like to know what people think about them. Any suggestions for improvement would be welcome.

In Nice, as in some other languages, it's possible to override the behavior of the [] operator. I've done this for lists, so that the [] operator now supports a number of new options, including slicing, filtering, and indexing relative to the end of the list, instead of the front.

First, we introduce a new symbol, "@", which means, "the last index in the list". Sometimes I think of it as "-0". So, given a list of ints from 0 to 6 called 'intList':


   intList[@] is 6,

   intList[@-1] is 5

Makes sense? This has the desirable property of making indexing reflective: 1 is the second element from the front, @-1 is the second element from the back.


from the front:     0    1    2    3    4    5



(or: )              0   0+1  0+2  0+3  0+4  0+5



                  ["a", "b", "c", "d", "e", "f"]



from the back:     @-5  @-4  @-3  @-2  @-1   @

Next, we add slicing, using the range operator we've had for a while now (and even in the manual, in the section on extended for loops).


   intList[1..2] is the list [1,2].

   intList[1..@-1] is a list of all but the first and last

       elements of ints, i.e., [1,2,3,4,5]

   intList[1..] is a list of all but the first element of intList

   intList[..] is a complete copy of intList

   intList[..@-1] is a list of all but the last element of intList

   intList[@-2..@-1] is the third-from-last and second-from-last: [4,5]

Notice that Nice's range is an inclusive range, as opposed to Python's half-open range. So where Python would write:


   intList[1:-1]

(where -1 represents the last item in the list) to mean all but the first and last items of the list, we write


   intList[1..@-1]

for the same thing. @ means the last item in the list, minus one makes it the second to the last item in the list, and ".." is the inclusive range operator which takes everything from index 1 to index @-1, including the end points.

There are also some more unusual variants, such as filtering:


   intList[int i => i % 2 == 0] is a list of all the even ints in intList, i.e.: [0,2,4,6]

Picking out a sequence of arbitrary indices:


   intList[[2,3,0,1, @]] is [2,3,0,1,6]

Assigning to a filter:


   intList[int i => i % 2 == 0] = 27 makes intList into: [27, 1, 27, 3, 27, 5, 27]

Assigning to arbitrary indices:


   intList[[0,2] = -3 makes intList into: [-3, 1, -3, 3, 4, 5, 6]

Assigning to a slice:


   intList[3..] = 9 makes intList into: [0,1,2, 9, 9, 9, 9]

   intList[3..] = [5,4,3,2] makes intList into: [0,1,2,5,4,3,2]

Removing a slice:


   intList.removeAt(3..) makes intList into: [0,1,2]

We've also debated adding support for a half-open range as "..!", e.g., 1..!4 to mean the same as 1..3, on the theory that the half-open range can be useful too in certain circumstances. Does this come up often enough to merit it? I'm not interested in adding "..." for this, as I would never be able to keep the meanings of ".." and "..." straight.

So what do you think of these new features? Good? Bad? Ugly? Let me know.