-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Shortcut for array[array.length - 1] #156
Comments
+1 - both Python and Ruby support this |
It's a great idea, but would it require wrapping runtime checks around all array accesses and hash["style"] property lookups? If so, it would probably incur a significant cost in terms of speed and generated code size. |
Now that you remind me, I think that's the reason why we didn't implement it before. The very best you could do is this:
But that's pretty nasty for every single non-numeric array access. Hmm. |
A compromise: how about having negative array indices meaningful only in the slice syntax? Eg, having The incremental cost of the feature would be smaller since slices are already more expensive than a lookup, and since slices are only meaningful for numerical indices in the first place. You could even have the compiler recognize the special case where both indices are the same expression, and just generate
when it sees
|
Another option would be to add a different array access syntax that is guaranteed to do bounds checking and automatically wrap around, eg.
|
I like the |
After thinking about all the issues raised here, and how they would interact... I don't think that there's a good way to add this for the (admittedly minor) gain it provides, while maintaining consistency. And it's not worth introducing a new syntax for. The only thing we could realistically do is straight transformations of negative array literals into the appropriate access, like so:
Into:
But then this would fail, probably unexpectedly:
It's very much something that needs to be added to the runtime, not the language. So, closing as a wontfix. If you come up with a way to make it work, we'll reopen. |
I really think introducing new syntax here is a good idea. In Ruby and Python, I've always been extremely bothered by the way array indices are zero-based when counting from the front By creating a new symbol, say |
That's a nice idea. To play devil's advocate, briefly: it's not just a syntactic convention in Ruby and Python, you can actually pass a negative value.
...could be indexed from the front or indexed from the rear, depending on the value of x. Reopening the ticket. |
That's indeed true, and I guess I'm playing devil's advocate from the other side. At the cost of brevity I considered mentioning that there may be advantages to the Ruby and Python approach when writing certain kinds of algorithms (where one might be imagining the elements of an array as a continuous "circle", rather than a line with a start point and a finish point at opposite ends). But it's nothing that can't be replicated with an extra line of code reseting the array index variable -- and in that sense it's just another form of syntactic sugar. The key point is that these hypothetical kinds of algorithms are the least common case. Simple array access is much more common, and therefore making simple array access less verbose and more intuitive is the bigger win. And for that reason I think a syntactic convention that allows zero-based negative indices is better than accepting actual negative values. I think at the very least we need to allow it for simple expressions. That's an easy win. For the larger expressions you mention, it's a more complicated matter, and I wrote down a bunch of ideas in my other ticket: http://github.com/jashkenas/coffee-script/issues/issue/382/ It's a long read -- guilty of thinking out loud rather than editing my thoughts in advance -- but in the end I decided that this makes the most sense:
These would expand out to:
And we also have a possibility of omitting zeros entirely (which I'm leaning towards as a good idea, but it might be too implicit for too little gain -- it's not much extra effort to just put the zeros in):
Obviously there are other possible approaches. It would be interesting to hear others' thoughts. |
Here's another obvious approach, which I think is what you were suggesting Jeremy -- only allowing the It might arguably be simpler, but I don't like it as much because it doesn't allow "pinching" parts from the middle of an array, which I think is a very common use-case:
|
Sorry Ben. I'm afraid that special symbols just to index the array from the rear is a little too much syntax for my taste. I looked through the CoffeeScript compiler to see how many times we look at the last element of the array, using this pattern:
And found 15 cases. But I can't imagine that switching those 15 cases to:
Would really be an improvement -- it's pretty mysterious what that second line is doing, especially to those unfamiliar with this ticket. More so when the first form isn't too onerous. Of course, if you have a particular script that comes up against this all the time, you can make a function for it:
Closing the ticket, once again. |
Thanks Jeremy. Although I disagree -- perhaps because the particular program I'm writing makes heavy use of these operations, and I think having them built into the language would make my code more readable -- it's a small issue in the scheme of things. I'm (still ;-) a big fan of Coffeescript, which is a huge improvement over vanilla JS, and, I think, a standalone achievement as a language (would still have value if it didn't compile down to JS). I guess the larger issue here is how much to deviate from what incoming members of the Python / Ruby / Javascript communities find "intuitive" due to prior experience with these languages. I have a bias toward throwing away understood conventions if it means creating something better, but I also understand the advantage of not mixing things up too much. And thanks for the suggestion, that's pretty much what I've been doing. Not as nice as inline syntax, but sorta does the job. |
One last thing: if you know what JS environment you are targetting, and you don't mind tampering with prototypes, you can kinda-sorta hack
It won't work everywhere, but it works in v8/node and spidermonkey. |
sethaurus: that's really neat. benlambert: Thanks for the civil response. Regardless of whether or not a particular feature winds up included, these discussions are fantastic to have on the record, and make the archive of issues a real treasure trove for language ideas. |
Thanks Jeremy, I enjoy the discussions too :) sethaurus: That's neat feature -- though unfortunately I'm developing client-side for the lowest common denominator all the way down to IE. I don't think progressive enhancement really works for language features -- though perhaps I should give this more thought :D |
Maybe I'm missing something obvious here, but why not just add a
With modification for it to return a range of objects, this could make even more semantic sense (eg, like ruby):
...rather than coming up with some non-obvious 0-based backwards indexing syntax. |
@brookr +1 |
'abcz'[-1..] works for me |
It seems to fail in this situation:
Using: CoffeeScript version 1.3.3 |
@da99: |
Just for anyone else who stumbles upon this this thread in future. To retrieve the last element of array, use (of course, if you can): my_array.pop() |
@gmile You do know that removes the last element of the array, right? |
... Wait, what ? |
@Nami-Doc that's so horrendously ugly that it's almost cute, except that it's very, very inefficient. |
This was obviously a joke |
I hoped so. :P |
Everyone knows the most efficient method is |
Want it. +1 |
+1 |
come on! |
Compile to something like `array.length > 0 ? array[array.length - 1] : void 0` See jashkenas/coffeescript#156 and others.
+1 |
+1 (note from top of the thread: array[-1] is not a workable syntax) |
Would compiling array access to something like this:
solve a problem? it shouldn't be a big performance hit, and seems to work with strings correctly. |
-1 Don't think it's necessary to add special syntax when a simple function would suffice: last = (arr) -> arr[arr.legnth - 1]
# And then use `last someArray`
# Or:
at = (arr, i) ->
len = arr.length
arr[(i % len + len) % len]
# And then use `at someArray, -1` Maybe adding new syntax for the array destructuring case where you don't want to get the slice of elements before the last one: [first, ..., last] = arr
# Or:
[..., secondToLast, last] = arr |
Which needs you to declare it at the top of each file, or require it, or include it or... |
@epidemian Well convention of using negative numbers to represent index from end is pretty well established. and if we went the route of "why introduce syntax if function suffices" we'd get just another variant of Lisp. |
Problem is it would be a big performance hit + unreadable JS output. That's why |
@xixixao Performance hit on doing one comparison and additions in (_x < 0 ? a.length + _x : _x) would be so insignificant that you'd probably wont notice it at all even in small loops (it'd be a fraction of millisecond). |
JQuery is popular because it's so easy, not because it has no overhead, and more an more people/frameworks recommenf avoiding it. I don't think the "<?" is not noticeable - we know the |
Totally agree with Nami-Doc. You would see the performance hit once you iterate over large arrays etc. But the point is not the overhead, it's the fact that you couldn't avoid avoid this compilation. Plus, the unfortunate implicit range direction is enough for me, I wouldn't want another case where I have to worry about hidden bugs because instead of an exception the index wrapped around. Explicit > implicit, imo. |
Messing with the prototype works, but why rewrite the accessor to support an obscure syntax, when adding a "last" function is 100% clear? |
Implement #156, Added expansion to destructuring
In my opinion, the only thing that needs a shortcut here is a way to get the last element of an array as a single expression. The CoffeeScript compiler used to have a Want the next to last element? Use Need to get an element at a possibly negative index? Use Want the last element? Idea: Use |
SugarJS does the Negative indexes are really nice to have, but they're problematic to implement, easy to live without, and we often end up wrapping their use with functions anyway. |
Sounds really great. |
Fix jashkenas#155 (RequireJS bug)
While implementing the parser, I've often wished that CoffeeScript supported negative array indexes, to peek at elements towards the end.
Do you all think it would be a worthwhile addition?
The text was updated successfully, but these errors were encountered: