Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negative indexes #42

Closed
eterps opened this issue May 15, 2020 · 8 comments · Fixed by #43
Closed

Negative indexes #42

eterps opened this issue May 15, 2020 · 8 comments · Fixed by #43

Comments

@eterps
Copy link
Contributor

eterps commented May 15, 2020

In the (TODO) doc comments of string.slice ( https://github.com/gleam-lang/stdlib/blob/master/src/gleam/string.gleam#L135 ), you see this example:

> slice("snakes on a plane!", from: -6, to: -1)
"plane"

Which surprises me because as a user of the slice function I would expect the function to be able to slice to the end of a string without having to know the length of that string beforehand.

So personally I expect to be able to do this:

> slice("freeby", from: -2, to: -1)
"by"

This is also how negative indexes work in Ruby for example (I'll have to check other languages though):

> "snakes on a plane!"[-6..-1]
=> "plane!"

Thoughts?

@eterps
Copy link
Contributor Author

eterps commented May 15, 2020

In Elixir enums suport negative indexes: https://hexdocs.pm/elixir/Enum.html#at/3

A negative index can be passed, which means the enumerable is enumerated once and the index is counted from the end (for example, -1 finds the last element).

@eterps
Copy link
Contributor Author

eterps commented May 15, 2020

With Elixir strings you can do:

iex(1)> "snakes on a plane!" |> String.slice(-6..-1)
"plane!"

In Ruby and Elixir you have range types where you have -1 representing the last element. ("snakes on a plane!" |> String.slice(-6, -1) is not something you can do in Elixir because the 3rd argument isn't an index, but the length of the slice to take).

@eterps
Copy link
Contributor Author

eterps commented May 15, 2020

I'm starting to think that Elixir's variant that specifies the length is the least confusing (i.e.: slice(string, start, len)):

iex(1)> "freeby" |> String.slice(-2, 2)
"by"
iex(2)> "snakes on a plane!" |> String.slice(-6, 6)
"plane!"
iex(3)> "snakes on a plane!" |> String.slice(-6, 5)
"plane"

@lpil
Copy link
Member

lpil commented May 15, 2020

Thanks for doing this research. I think that last example is clear

So would that be slice(str, from: -8, up_to: 4) with labels? From memory I think this matches the list take/drop functions.

@eterps
Copy link
Contributor Author

eterps commented May 15, 2020

Thanks for doing this research. I think that last example is clear

👍

So would that be slice(str, from: -8, up_to: 4) with labels? From memory I think this matches the list take/drop functions.

In the list take/drop functions the labels have a different meaning:

// take(from list: List(a), up_to n: Int) -> List(a)
take(from: task_list, up_to: 4)
// Or:
task_list |> take(up_to: 4)

For string.slice I would suggest:

invoice_label |> slice(at_index: 6, length: 8)
// Or:
slice(from: invoice_label, at_index: 6, length: 8)

Then it's unambiguous and the from: is used similar to the list take/drop functions.

What do you think?

@lpil
Copy link
Member

lpil commented May 16, 2020

Looks good. What about length -> up_to? As you may not always get that many graphemes

@eterps
Copy link
Contributor Author

eterps commented May 16, 2020

Looks good. What about length -> up_to? As you may not always get that many graphemes

I agree, that would also make it more consistent with the up_to label used in other functions.

invoice_label |> slice(at_index: 6, up_to: 8)

I do think some people could interpret it as in index and that length would make that less ambiguous, but to me personally up_to sounds clear enough 👍

@lpil
Copy link
Member

lpil commented May 16, 2020

Good point, let's go for length then.

@eterps eterps mentioned this issue May 17, 2020
@lpil lpil closed this as completed in #43 May 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants