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

Counting from the end of an array #382

Closed
ben-x9 opened this issue May 18, 2010 · 8 comments
Closed

Counting from the end of an array #382

ben-x9 opened this issue May 18, 2010 · 8 comments

Comments

@ben-x9
Copy link

ben-x9 commented May 18, 2010

I find this inelegant:

myListOfItems[myListOfItems.length-1]

myListOfItems[0...myListOfItems.length]

The reason this feels ugly, I think, is the repetition of the variable name.
An obvious improvement would be negative values ala Python and Ruby:

myListOfItems[-1]

myListOfItems[0..-1]

But the discrepancy between a zero-based index when counting from the front and a one-based index when counting from the back makes this potentially confusing.

If the primary goal is to remove the need to include the variable name twice, then there are many possible approaches. To make both directions zero-based, we could add a special character that denotes counting backwards from the end of the array:

myListOfItems[<0]

myListOfItems[0..<0]

Or we could simply have a symbol that takes the place of "myVariableName".length:

myListOfItems[@-1]

myListOfItems[0...@]

Which approach is best may be debatable, but all these approaches are better than the status quo.

@weepy
Copy link

weepy commented May 18, 2010

Well the obvious thing is to just omit an end, e.g.

ma_array[x..]

Some people didn't like this for one reason or another. I thought it made alot of sense and certainly beats:

my_array[x...my_array.length]

@ben-x9
Copy link
Author

ben-x9 commented May 18, 2010

That's not a bad idea for the use case you gave, however it doesn't cover cases where we only want a single item from the list, and not a range. It also doesn't cover ranges that pull a number of items from the back of the list.

Would be great if the dots had a direction attached, instead of assuming the range is always front-to-back:

my_array: ['a', 'b', 'c', 'd', 'e']

#inclusive
my_array[2>>]  ->  ['c', 'd', 'e']  
my_array[>>2]  ->  ['a', 'b', 'c']  
my_array[<<2]  ->  ['c', 'b', 'a']  
my_array[2<<]  ->  ['e', 'd', 'c']  

#exclusive
my_array[2>>>]  ->  ['d', 'e'] 
my_array[>>>2]  ->  ['a', 'b'] 
my_array[<<<2]  ->  ['b', 'a'] 
my_array[2<<<]  ->  ['e', 'd'] 

#single item
my_array[<0]  ->  ['e']  
my_array[<1]  ->  ['d'] 

@ben-x9
Copy link
Author

ben-x9 commented May 18, 2010

Well reversing the list as part of the operation is probably a bad idea. This would be better.

my_array: ['a', 'b', 'c', 'd', 'e', 'f']

#inclusive
my_array[3>>]  ->  ['d', 'e', 'f']  
my_array[>>3]  ->  ['a', 'b', 'c', 'd'] 
my_array[<<3]  ->  ['a', 'b', 'c'] 
my_array[3<<]  ->  ['c', 'd', 'e', 'f'] 

#exclusive
my_array[3>>>]  ->  ['e', 'f']  
my_array[>>>3]  ->  ['a', 'b', 'c'] 
my_array[<<<3]  ->  ['a', 'b'] 
my_array[3<<<]  ->  ['d', 'e', 'f'] 

#single item
my_array[<0]  ->  ['f'] 
my_array[<1]  ->  ['e'] 

@ben-x9
Copy link
Author

ben-x9 commented May 18, 2010

Of course this notation makes it cumbersome to extract a large range from the middle of the list, e.g. everything between the first two items and the last two items.

I think a simple notation denoting a zero-based index counted from the back-end is best:

my_array[1..^1] #everything between the first item and the last item
my_array[2..^2] #everything between the first two items and the last two items

my_array[2..] #everything except the first two items
my_array[..^2] #everything except the last two items

my_array[...2] #first two items only
my_array[^2...] #last two items only

@ben-x9
Copy link
Author

ben-x9 commented May 18, 2010

...or if omitting an end is undesirable:

my_array[2..^0] #everything except the first two items
my_array[0..^2] #everything except the last two items

my_array[0...2] #first two items only
my_array[^2...^0] #last two items only

though I personally agree with weepy that allowing the omission is fine.

@StanAngeloff
Copy link
Contributor

I've been using my own implementation for quite some time now. It isn't the most elegant solution, but it gets the job done and as you've said, it's much better than the status quo.

Unfortunately native negative indices are out of the question. obj[i] where i: +/- 1 would mean we have to do checks on each index access. This is why in my implementation you have to explicitly specify the - to force counting backwards, i.e., obj[i] is obj[i] for every i. obj[- i] is obj[obj.length - i]. It works for strings, it works for slices, it even works in assignments.

I agree with weepy we should enable slices like obj[i..], probably best to start another ticket for that, keep the conversation separate?

Of the proposed syntaxes, I don't find any of them to be eye appealing. <<< or ^ don't expose much of the underlying operating that is going to be performed. Unfortunately I fail to think of anything better.

I recall there was a suggestion at one point to ditch slices in their form ... and use :: instead. This seems like a reasonable thing to do? Here is why:

a: [b..., c]            # merge values from b and c in a
a: [b...c]              # generate a range b to c in a
a: d[b...c]             # slice b to c from d
a: d(b...)              # call d with values from b
a: (b...)               # assign b to a
a: (b...) -> b[0]       # variadic function
a: [0..10]; b: [0...10] # I never recall which one is the inclusive, should be the one with more dots in it, no? wrong!

and the alternative:

a: [b..., c]               # expand b
a: [b...c]                 # ... as a range
a: d[b::c]                 # :: is a slice
a: d(b...)                 # expand b
a: (b...)                  # expand b in a, assignment
a: (b...) -> b[0]          # expand arguments in b
a: [0::10]; b: [0::10 - 1] # explicit

and there we have it -- distinguishing between expands ... and splats ::.

@jashkenas
Copy link
Owner

We had a ticket about this a while back ... http://github.com/jashkenas/coffee-script/issues/issue/156

And, although Stan's proposal for array[- i] is quite tempting ... it's a little too implicit for my taste. Closing this ticket as a wontfix for the same reasons as the first time around.

@ben-x9
Copy link
Author

ben-x9 commented Jun 9, 2010

I popped a comment on the end of the original ticket. In brief I really think Stan's proposal is a good one if we introduce new syntax to avoid potential confusion. E.g:
array[<0]
Into:
array[array.length - 1]

christopherstyles added a commit to christopherstyles/react-rails that referenced this issue Mar 20, 2015
There is an issue with the latest version of `coffee-script-source`
outlined in jashkenas/coffeescript#382.

The `react-rails` gemspec specifies a `~>1.9` version of
`coffee-script-source`, which makes it impossible to back out of
its most recent version in order to avoid the errors (for example,
if you want to specify `~>1.8` in your app).

This change lowers the dependency version in the `react-rails`
gemspec so that a user can specify a lower working version.
HardCarrier pushed a commit to HardCarrier/react-rails that referenced this issue Jan 9, 2023
There is an issue with the latest version of `coffee-script-source`
outlined in jashkenas/coffeescript#382.

The `react-rails` gemspec specifies a `~>1.9` version of
`coffee-script-source`, which makes it impossible to back out of
its most recent version in order to avoid the errors (for example,
if you want to specify `~>1.8` in your app).

This change lowers the dependency version in the `react-rails`
gemspec so that a user can specify a lower working version.
goldapple911 added a commit to goldapple911/react-rails that referenced this issue Aug 15, 2023
There is an issue with the latest version of `coffee-script-source`
outlined in jashkenas/coffeescript#382.

The `react-rails` gemspec specifies a `~>1.9` version of
`coffee-script-source`, which makes it impossible to back out of
its most recent version in order to avoid the errors (for example,
if you want to specify `~>1.8` in your app).

This change lowers the dependency version in the `react-rails`
gemspec so that a user can specify a lower working version.
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants