Arc Forumnew | comments | leaders | submitlogin
List slice notation, now on my fork (github.com)
2 points by Pauan 4956 days ago | 6 comments


2 points by Pauan 4956 days ago | link

You will need to use my fork (rather than base ar) for two reasons:

1) I fixed setforms so it passes all the args to sref, rather than only the first.

2) My fork has an awkward and inefficient (but working) form of defcall.

I hope to get both those things into ar soon, but for now, just use my fork.

---

After loading up "lib/slices.arc", you should be able to both get and set slices of a list:

  (= foo '(1 2 3 4 5))

  (foo 2 5)              -> (3 4 5)     ; this is the slice
  (= (foo 2 5) '(6 7 8)) -> (1 2 6 7 8) ; foo is now this
It also supports negative start and end indices, like Python. So -1 is the last element, -2 is the second-to-last, etc:

  (foo -3 -1)             -> (6 7)
  (= (foo -3 -1) '(9 10)) -> (1 2 9 10 8)
And you can use nil as either the start or end to mean 0 and (len foo) respectively:

  (foo 2 nil) -> (9 10 8)
  (foo nil 2) -> (1 2)
I also changed ordinary element notation so it understands negative indices:

  (foo -1) -> 8
  (foo -2) -> 10
In case it wasn't obvious from the examples above, slices use half-open notation, just like Arc's cut and Python slices. In fact, Arc slices should be exactly the same as Python slices, with two exceptions:

1) If the start index is higher than the end index, my implementation will throw an error:

  (foo 5 3) -> error: start index must be smaller than the end index
In Python, as near as I can tell, that will always return an empty list. I'm not entirely sure how to handle that situation, so for now it just throws an error. If you can think of a useful behavior for that, please share.

Lastly, you can now delete elements/slices by assigning a slice to nil:

  (= (foo 0 1) nil)   -> (2 9 10 8)
  (= (foo 2 nil) nil) -> (2 9)
2) However, you cannot set the entire list to nil:

  (= (foo nil nil) nil) -> error: cannot set the entire list to nil
So the idiomatic Python way of using `del foo[:]` won't work. Instead, you'll have to set the variable to nil:

  (= foo nil)
This is because of the difference between arrays (in Python) and lists (in Arc). I can, of course, special-case this with the `del` operator, but I haven't done so yet.

-----

2 points by akkartik 4955 days ago | link

I spent several hours trying to get slices into wart. What I have is extremely unsatisfying, and I'm inclined yet again to blame Common Lisp.

Reading slices looks fine if a little lumpy: https://github.com/akkartik/wart/commit/3433b5e478d37b5f2c76...

(Now that we can't use ssyntax the lisp-2 rears its ugly head again:

  (call l 0 3)
..but I'll slide past that without further comment.)

Writing slices, however, is extremely ugly: https://github.com/akkartik/wart/commit/9a292064188c6fa072c7...

wart translates '= to setf and relies on Common Lisp's defsetf for overriding '=. But you can't just appropriately set the variable inside defsetf. Assigning to a place can't change the aggregate it belongs to.

Not only is this implementation verbose, there's a bug in it that you can drive a truck through: setf can never delete an entire list. I can't see any way to fix it short of reimplementing assignment in wart.

-----

1 point by Pauan 4956 days ago | link

I would also like to note, that my implementation actually changes the list with scar and scdr, rather than using zap (or similar) to overwrite it.

Also, I basically just overwrite `cut`, but that's another thing I hope to get into base ar soon, since `cut` doesn't handle a start index that is nil or negative.

-----

1 point by Pauan 4956 days ago | link

Also, unlike Python, this doesn't support step notation. It would be neat to have, but it's not really a huge deal, so kinda low priority.

-----

1 point by akkartik 4956 days ago | link

I had no idea python slices could take steps!

http://docs.python.org/release/2.3/whatsnew/section-slices.h...

-----

1 point by Pauan 4955 days ago | link

Yeah, Python is actually pretty good at dealing with lists, given how it has slices + steps, list comprehensions, etc. It also has a bunch of neat stuff for dealing with iterators, which I consider to be one of the strengths of Python. So let's steal the good stuff and put it into Arc, shall we?

-----