# Dollar syntax for Rust

**URL:** <https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149>\
**Category:** language design\
**Created:** [February 5, 2016, 4:22pm UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149 "2016-02-05T16:22:30Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![leonardo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leonardo/32/1344_2.png) [@leonardo](https://internals.rust-lang.org/u/leonardo)\
**Post date:** [February 5, 2016, 4:22pm UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/1 "2016-02-05T16:22:30Z")

</div>

In numerical processing code like you write in Matlab, Python Numpy, Julia and so on, you often slice arrays, both 1D, 2D and more:

[https://docs.scipy.org/doc/numpy-dev/user/quickstart.html](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html)

In such code you sometimes have complex expressions that contain several slicing operations, so to keep that code readable you _really_ want a compact and noise-free slicing syntax.

Rust offers a readable array slicing syntax, but there’s something I’m missing in Rust, that I’d like Rust to steal from D. But first I show some examples with Python code (Python REPL):

```
>>> s = "abcdefgh"
>>> s[2:]
'cdefgh'
>>> s[2:-1]
'cdefg'
>>> s[2:-2]
'cdef'
>>> s[-2:]
'gh'
>>> s[-4:-2]
'ef'

```

In Python the index -1 refers to the last item, -2 is the penultimate, and so on. This is handy because you often enough want to slice taking the end of the array as reference point.

But handling negative numbers like that slows down all the array access, and I don’t like when sometimes, because of a bug I create a negative index and my Python code still keeps running, and giving wrong results instead of raising an out of bounds exception.

The D language has solved the problem efficiently, more safely, and in a sufficiently compact way using the “$” operator. This is D code equivalent to the Python code above:

```
void main() {
    import std.stdio;
    auto s = "abcdefgh";
    s[2 .. $].writeln;
    s[2 .. $ - 1].writeln;
    s[2 .. $ - 2].writeln;
    s[$ - 2 .. $].writeln;
    s[$ - 4 .. $ - 2].writeln;
}

```

The outputs is the same (D strings/dstrings/wstrings can be sliced):

```
cdefgh
cdefg
cdef
gh
ef

```

“`$`” means the length of the array, but you can’t use it like “`a.$`”. So the D code:

```
a[$ - 2]
b[$ - c[$ - 2]]
d[random(0, $)]

```

Is equivalent to the Rust code:

```
a[a.len() - 2]
b[b.len() - c[c.len()- 2]]
d[random(0, d.len())]

```

As you see in the `$` refers to the length of the innermost array.

So $ makes the code shorter, but also safer because it’s more DRY, you don’t have to state the name of the array twice.

So I’d like the “$” operator in Rust slices/arrays/vectors too.

In D you can also overload the “$” in library code if you define the “opDollar” method in struct/class, so you can use a nice slicing syntax in library-defined matrices too, for numerical processing:

```
mat[$-1, 0]

int i = r[$-1, 0]; // same as: r.opIndex(r.opDollar!0, 0),
                    // which is r.opIndex(r.width-1, 0)
int j = r[0, $-1]; // same as: r.opIndex(0, r.opDollar!1)
                    // which is r.opIndex(0, r.height-1)

```

More info about `opDollar` usage:

[https://dlang.org/spec/operatoroverloading.html](https://dlang.org/spec/operatoroverloading.html)

`opDollar` is used in the `ndslice` in the standard library:

[https://dlang.org/phobos/std\_experimental\_ndslice.html](https://dlang.org/phobos/std_experimental_ndslice.html)

[https://dlang.org/phobos/std\_experimental\_ndslice\_slice.html#.sliced](https://dlang.org/phobos/std_experimental_ndslice_slice.html#.sliced)

You can use it like:

```
t[3..$,0..3,0..$-1]

```

That is similar to the more compact NumPy syntax:

`t[3:,:3,:-1]`

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [February 6, 2016, 2:03am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/2 "2016-02-06T02:03:25Z")

</div>

I’ve definitely missed `$` from D, myself.

Obviously, though, Rust can’t use `$` literally. `#` is _probably_ okay, given it would otherwise be followed by `!` or `[`.

Another reason to have something like this is that it allows you to do this…

```rust
s.some_method_that_returns_a_slice()[1..$-1]

```

…without having to bind the result to a temporary variable _first_.

I don’t know about the multidimensional indexing thing, though. Frankly, I’m quite disappointed that Rust has _kind of_ closed that door already for the moment, but you _can_ do it with tuples. Problem with _that_ is that this means Rust’s equivalent to `$` can’t do the template trick. I suppose you can make `$` return a tuple and index manually, giving you…

```rust
t[(3..#.0, 0..3, 0..#.2-1)]

```

Of course, Rust can’t return non-slices out of indexing, so it’s a bit of moot point.

---

<div class="post-metadata">

**Author:** ![niconii](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/niconii/32/1137_2.png) [@niconii](https://internals.rust-lang.org/u/niconii)\
**Post date:** [February 6, 2016, 2:29am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/3 "2016-02-06T02:29:03Z")

</div>

> [@DanielKeep](#):
>
> Obviously, though, Rust can't use $ literally.

To clarify what is obvious to our macro overlord, but maybe not to everyone, `$` is used in macros, so it could potentially cause issues. That said, I'm not sure I can think of a case where it would be ambiguous; is there a situation where `$` could end up being followed by an ident or `(`?

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [February 6, 2016, 2:32am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/4 "2016-02-06T02:32:26Z")

</div>

Actually, I just meant that `$` is the “macro pixie dust” symbol. Having it used both at macro expansion _and_ in regular code would make reading macros significantly more painful than it already is.

Macros are hard _enough_ to read, thankyouverymuch. `$` is _ours_. You can’t have it. \*_holds `$` tight_\*

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [February 6, 2016, 4:24am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/5 "2016-02-06T04:24:39Z")

</div>

I’ve experimented with just simply supporting signed range ends, so in ndarray, `1..-1` is a range equivalent to `1..axis_length - 1`.

That works well, you can even use for example `-3..-1` to pick out the two elements before the last.

The misergonomy comes from the fact that the boundaries are always `isize`, while lengths and indices that you often use to compute these things are usually `usize`.

If I add _more_ trait implementations, so that slicing using `usize` ranges is possible as well as `isize`, something interesting happens: Then `1..-1` suddenly says that the array does not support slicing by the type `i32` (!).

---

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [February 10, 2016, 8:30am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/6 "2016-02-10T08:30:22Z")

</div>

We can just support negative indices the same way that Ruby does with current Rust by implementing `Index<Range<isize>>` and friends. This does not need to slow down non-negative indices since those will continue to use `Index<Range<usize>>`. I hope type inference works the way we want it here…

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [February 10, 2016, 4:22pm UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/7 "2016-02-10T16:22:26Z")

</div>

In my experience, type inference does not help you there (see my post). It will be ambiguous if you are using literals (like a range `1..-1`).

---

<div class="post-metadata">

**Author:** ![nodakai](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nodakai/32/6161_2.png) [@nodakai](https://internals.rust-lang.org/u/nodakai)\
**Post date:** [February 13, 2016, 6:49am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/8 "2016-02-13T06:49:55Z")

</div>

One papercut in Python slicing syntax when we count from the end of the input array is, we need to choose different syntaxes depending on whether to include the last element or not. For example,

```
def drop_last(a, n):
  return a[0:-n]

```

No `n` (except `-len(a)`) can have `get_slice(a, n)` return the entire copy of the `a` array:

```
>>> drop_last([1,2,3], 0)
[]
>>> drop_last([1,2,3], 1)
[1, 2]
>>> drop_last([1,2,3], 2)
[1]
>>> drop_last([1,2,3], 3)
[]

```

We need to change to this syntax: `a[m:]`

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:25am UTC](https://internals.rust-lang.org/t/dollar-syntax-for-rust/3149/9 "2019-03-25T08:25:45Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
