In String.prototype.slice(), should .slice(0,-0) and .slice(0,+0) output the same result?
Asked Answered
A

1

11

I came across this quirk while trying to optimise string pluralisation in a game of code golf. I had the idea to write strings as plurals and then use substr to cut the last character off, conditionally:

var counter = 1;
var myText = counter + " units".substr(0, 6-(counter===1));

It's fine - it does what I wanted. But looking at the MDN docs for String.prototype.slice(), I thought I had found a way to make it even shorter, by using passing negative zero as the second argument to the function. From the docs:

endSlice

Optional. The zero-based index at which to end extraction. If omitted, slice() extracts to the end of the string. If negative, it is treated as sourceLength + endSlice where sourceLength is the length of the string (for example, if endSlice is -3 it is treated as sourceLength - 3).

var myText = counter + " units".slice(0,-(counter===1));

This evaluates to .slice(0,-1) when counter is equal to 1, which would chop the last letter from the string, or it would otherwise evaluate to .slice(0,-0), which according to the docs should mean 0 characters were subtracted from the length of the string being operated upon.

As it happens, -0 is treated the same as +0 by String.prototype.slice. I wondered if this was a convention, to treat -0 as being the same as +0 (I know, for instance, -0 === +0 evaluates to true). I thought to look at String.prototype.substr, but +0 and -0 are supposed to be handled the same way in that function.

Does anyone have any greater insight into this? Is there some basic convention in the language design that states that, while signed zero is a language feature, it should be ignored, except in certain scenarios (like 1/-0)?

tl;dr I'm salty that I can't make jokes about winning code golf by slicing.

Astonied answered 13/9, 2016 at 0:23 Comment(7)
The standard also says "If end is negative, it is treated as sourceLength+end where sourceLength is the length of the String." I think they weren't careful enough about the word "negative" here.Marelya
How would you implement "if negative"? In my code I test that by saying if (val < 0), and given that -0 < 0 returns false...as it should: imagine if we had to write all of our code to distinguish between -0 and +0...Bridget
The second parameter is coerced to an integer (by ToLimit) before being compared against zero. Integers do not have a negative zero. This is explained in painstaking detail in the ECMA spec (which only true gluttons for punishment will read). MDN is a simplified description.Impetuous
-0 is just a floating point representation of real world zero, just like +0.Bork
@Bridget while researching it, I found that Javascript does provide a few ways to test for positive v negative zero. For instance: 1/-0 === -Infinity whereas 1/0 === InfinityAstonied
Yes, but my point was for "normal" operations you shouldn't need to distinguish between them. If using val < 0 did not work for "normal" cases that would lead to all sorts of bugs.Bridget
That's fair enough - and I agree, bugs aside, having to distinguish between +0 and -0 all the time would be headache-inducing.Astonied
P
2

From a mathematical perspective there is no negative zero. Positive is any number greater than zero, and negative is any number smaller than zero. Zero is neither of those. So I guess the behaviour you described is correct.

A real number may be either rational or irrational; either algebraic or transcendental; and either positive, negative, or zero.

https://en.wikipedia.org/wiki/Real_number

Although, because in programming we work with floating point numbers, which are an approximation of real numbers, there is a concept of -0, which could be a representation of a negative number too close to zero to be represented otherwise - http://www.johndcook.com/blog/2010/06/15/why-computers-have-signed-zero/


Regarding your javascript, you could write it as:

var counter = 1;
var myText = counter + " unit" + (counter > 1 ? "s" : "");
Petulance answered 13/9, 2016 at 1:54 Comment(4)
Well, not "before", floating point numbers are IEEE754. Not sure whether the standard itself puts any semantics (like "a negative number too close to zero to be represented otherwise") into the -0 value, but I hardly doubt it.Greenburg
@Greenburg - I don't think it is a matter of definition, but rather a physical limitation, forcing numbers to be rounded at some point. Anyway, I am not an expert on the subject, and have never come across this problem myself. I just though I would point out that the concept exists in programming, even though it is not mathematically relevant. Please feel free to edit the answer (or add a new one) with more details.Petulance
The answer is fine, with just one thing: it puts some extra point that "which could be a representation of a negative number too close to zero". Which I don't find correct: you can have exactly -0 and mean exactly that, so that it would not be an approximation or a rounding error. I'd remove that part at all.Greenburg
Of course, there are many ways to write my example... I ended up using a slightly stomach-churning hardcoded length with substr: counter + " units".substr(0,6-(counter===1)), but a normal ternary like yours is the shortest way I think. Edit: please don't read into my code... I was looking for deliberately esoteric ways of doing this!Astonied

© 2022 - 2024 — McMap. All rights reserved.