See also the discussion page.

Slice syntax

For convenience (inspired by Python) and early-binding optimization opportunities, allow indexed access to string characters.

Character indexing

First, a special case left out of Edition 3:

var s : String = "hello"
print(s[4])              // prints 'o'

As proposed in bug fixes, this example shows indexed read access to string characters. s[4] is equivalent to s.intrinsic::charAt(4), which allows for compile-time binding to the intrinsic::charAt method of class String. In such a trivial example, a good compiler could optimize the program to print(’o’). Lacking a type annotation on the variable, or without a compilation step that analyzes types, s[4] would be evaluated using a run-time “get” of id ‘4’ from the object denoted by s.

Slice stepping

Second, extend Array.prototype.slice and String.prototype.slice to take an optional third parameter beyond start and end, the step. This parameter is converted using ToInteger and the result must not be 0. Here is the revised String.prototype.slice from ECMA-262 Edition 3

1. Call ToString, giving it the this value as its argument.
2. Compute the number of characters in Result(1).
3. Call ToInteger(start).
4. If end is undefined, use Result(2); else use ToInteger(end).
5. If Result(3) is negative, use max(Result(2)+Result(3),0); else use min(Result(3),Result(2)).
6. If Result(4) is negative, use max(Result(2)+Result(4),0); else use min(Result(4),Result(2)).
7. If step is undefined, use 1; else use ToInteger(step).
8. If Result(7) is 0 throw a TypeError.
9. Let s be the empty string.
10. If Result(7) > 0 then
11.   For (i = Result(5); i < Result(6); i += Result(7)) s += Result(1)[i].
12. Else
13.   For (i = Result(5); i > Result(6); i += Result(7)) s += Result(1)[i].
14. Return s.

The length property of both slice methods is 3, not 2 as in ES3.

Slice bracket syntax

Third, building on indexed access to elements of strings and arrays, using intrinsic::slice as a method on both String and Array, support a Python-like syntax for slicing:

var s : String = "hello, world"
print(s[3:5])                      // prints 'lo'
print(s[10:])                      // prints 'ld'
print(s[::-1])                     // prints 'dlrow ,olleh'
var a : Array = [0,1,2,3,4,5,6,7]
var b = a[2:6]; print(b)           // prints '2,3,4,5'
var c = a[-6:-2]; print(c)         // prints '2,3,4,5'
var d = a[:2]; print(d)            // prints '0,1'
var e = a[::2]; print(e)           // prints '0,2,4,6'

As in Python, a slice operator has the form seq[start:end:step], where start is the starting index, end is the fencepost – one greater than the last index to slice, and step is the optional increment from start if positive or decrement from end if negative. If start is not given, 0 is used. If end is not given, seq.length is used. If start or end is negative, seq.length is added to it. After this step, any value not in [0, seq.length] is clamped to the nearest bound in that interval. If step is undefined, 1 is used; else ToInteger(step) must be non-zero. Any of start, end, and step may be omitted, and trailing colons may be omitted, but at least one colon is required to denote a “full” or “copying” slice: seq[:].

Expression syntax based on the current grammar but using EBNF:

Brackets ::= "[" Expression? ":" Expression? (":" Expression?)? "]"

Brendan Eich 2006/03/24 16:56

Did you mean:

Brackets ::= "[" Expression? ":" Expression? (":" Expression)? "]"

That is, that the Expression after a second colon is not optional?

Jeff Dyer 2006/11/21 12:45

No, I meant what I wrote ;-). See Python’s behavior:

Python 2.5b3 (r25b3:51066, Aug  3 2006, 12:48:59) 
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "hello"
>>> s[::]

Brendan Eich 2006/11/21 16:39

No, I meant what I wrote ;-).

I suspected you might have. Okay, let’s do what you said, and Python does.

Jeff Dyer 2006/11/21 18:09

proposals/slice_syntax.txt · Last modified: 2007/12/11 01:05 by graydon
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki