tc39 / proposal-array-last

A JavaScript TC39 Proposal for getting the last element from an array
311 stars 13 forks source link

naming about `end` #11

Closed mysticatea closed 6 years ago

mysticatea commented 6 years ago

end is well-known as the location of the next of the last element. For example, end is used as the end (exclusive) of range in Array.prototype.slice(start, end) and Array.prototype.fill(value, start, end). So I think that anArray.end may cause confusion. Especially, anArray.end = 1 looks like the assignment to the next of the last element.

ljharb commented 6 years ago

I’d be very surprised if a non-negligible number of users even knew about the spec names for those arguments, or thought about it in those terms.

Regardless, though, “padEnd”, “endsWith”, and “trimEnd” are far more prominent examples of “end means the end” - that’s what I’d expect people would think of.

keithamus commented 6 years ago

@mysticatea if you have a better name I'm certainly all ears. last has webcompat issues, other ideas were floated but all generally unworkable.

mysticatea commented 6 years ago

I'm sorry, I have no idea. Maybe lastItem.

@ljharb I think I'm pulled by C++ knowledge :smile:

Alexsey commented 6 years ago

I think that end is the best. But if someone would really like to have something else then utmost is also fitting well with meaning, it's not too long and probably would have no associations with other APIs

keithamus commented 6 years ago

The British citizen in me likes the idea of utmost. Other ideas:


In all seriousness. We can bikeshed on the name, probably ad infinitum. end works, I mean its not the best name, but its succinct, and accurately describes the operation (even if the name has other connotations in the spec). If there are serious issues with end Im happy to discuss other options, but I think the rubric should be:

addaleax commented 6 years ago

I like lastItem or lastElement as well, tbh.

Yes, it’s a compound word, but when I’m thinking about a coding newbie, I don’t think it would be obvious to them at all whether .last or .end refer to an element or an index – in the case of end, I would honestly expect them to guess “index”.

Being explicit never really hurt anybody, and I really feel that end → index-after-last-item connotation from other programming languages is going to confuse the hell out of at least me. 😄

adamauckland commented 6 years ago

I reacted to @addaleax because I also feel that "end" is possibly a bit vague whereas lastItem and lastElement are quite explicit.

goodwin64 commented 6 years ago

Agree with @addaleax, there could be provided both options

const myFancyArray = ['dog', 'cat', 'bird'];
console.log(myFancyArray.lastItem);    // 'bird'
console.log(myFancyArray.lastIndex);   // 2
console.log(myFancyArray.length);      // 3

in this proposal.

coryasilva commented 6 years ago

I would like to see head, last and tail, borrowing from Haskell.

const myArray = [ 1, 2, 3 ]
assert( myArray.last === 3 ) // like the return from pop()
assert( myArray.head === 1 )  // like the return from shift()
assert( myArray.tail === [ 2, 3 ] ) // like the mutated result of shift()
shhac commented 6 years ago

@coryasilva If you're suggesting including tail as defined in Haskell, then I think Haskell's init should also be considered here

const arr = [1, 2, 3];
assert(arr.init === [1, 2]); // Same as arr.slice(0, -1);
assert(arr.tail === [2, 3]); // Same as arr.slice(1);
dantman commented 6 years ago

Random bikeshed idea, probably not really worth it. But, how about Infinity as the key?

Infinity becomes "Infinity" when you try to use it as a property key.

;) In other words you'd be able to write this:

const arr = [1, 2, 3];
assert( arr[Infinity] === 3 ); // As if you were trying to use the index `Infinity`
// This actually works today
const arr = [1, 2, 3];
arr.slice(1, Infinity); // => [2, 3]
// And Infinity even works with type checking
const arr:Array<number> = [1,2,3];

function incrementIndex(i:number):void {
  arr[i] += 1;
}

incrementIndex(0);
// incrementIndex('end'); // Type error and "string isn't an array index" without the explicit `:number` type
incrementIndex(Infinity); // Infinity is a number, and flow also doesn't say Infinity isn't an array index

Try it yourself.

ljharb commented 6 years ago

You can already have any own string property on any array (part of the basic nature of JS, which i don’t think type systems accommodate), so that wouldn’t work:

var a = [];
a.Infinity = true;
a[Infinity] // true
dantman commented 6 years ago

@ljharb I'm aware of that. But how is that any different from 'end'?

var a = [];
a.end = true;
a['end'] // true

We're just bikeshedding over a name for that property, and neither 'end' or 'Infinity' are valid array indexes or valid values for new Array(size).

ljharb commented 6 years ago

Ah, i misunderstood your suggestion - you’re saying we should name the getter “Infinity”?

I see how that would work, but i think the likelihood of someone accidentally putting an Infinity in where they intended a specific index is a problem - currently they’d get undefined, but with your change they might not notice the bug.

fuchsia commented 6 years ago

I guarantee calling it end would lead to me writing *vector.end() when I switched to C++ after a period of javascript. There'd be a similarly large cognitive "thunk" when I switched back to javascript, even if the bugs wouldn't be quite so dramatic. (I also use end in the C++ sense elsewhere in my code.)

C++ itself uses vector.back() for this and there are plenty of other good names in the thread -- I'm not advocating for any one in particular; but I am strongly against calling it end.

ljharb commented 6 years ago

Switching languages back and forth isn’t a use case we prioritize (altho consistency with other languages is nice, when achievable and when there’s a broad existing convention). JS API needs to work well for JS.

gmattie commented 6 years ago

I would suggest maintaining something similar to the age old, tried and true Array.prototype.pop(), which removes and returns the last element of an array. However, since the idea here is not to remove the element, perhaps something like Array.prototype.prePop() could suffice?

Likewise, a companion method for Array.prototype.shift(), which removes and returns the first element of an array could be Array.prototype.preShift().

The prefix pre- infers that there will be a removal of the item, so there is room for improvement with this suggestion to describe only getting the element without removing it.

ljharb commented 6 years ago

If you wanted to go with stack-like semantics (Arrays are kind of a hybrid List/Stack/Queue), you'd use "peek" for the last item; but that wouldn't provide a way to set it, and arrays are more a List than a Stack or a Queue anyways.

keithamus commented 6 years ago

@gmattie please see https://github.com/keithamus/proposal-array-last#other-considered-options for rationale on why prePop/preShift/peek are not something I wish to propose.

I will be presenting this in the March meeting, and will bring up the lastItem/lastIndex proposal. I still believe end is the most intuitive but I would like to hear from other what their intuitions are on this.

keithamus commented 6 years ago

Who am I to argue with Twitter polls?

https://twitter.com/Keithamus/status/973889308158578689

lastItem is is.

7fe commented 6 years ago

I would prefer end. :( Twitter polls are not particularly official at least with github when can see the voters.

MadDeveloper commented 6 years ago

No doubt that last() and end() were the best! If some propositions can be added, I've ones: pickLast(), takeLast(). A little bit more verbose than others, but it's easy to understand their role.

seven-deuce commented 5 years ago

I like Array.prototype.last it is self-exploratory! but if that's not possible, I suggest Array.prototype.lastly or Array.prototype.final