Pure function given strictly equal arguments yielding non-strictly equal results

后端 未结 6 625
执念已碎
执念已碎 2021-01-04 12:59

Below is a pure function f for which f(a) !== f(b) despite a === b (notice the strict equalities) for some values of a<

相关标签:
6条回答
  • 2021-01-04 13:22

    In ECMAScript 3, another example where === behaves surprisingly is with joined functions. Consider a case like this:

    function createConstantFunction(result) {
        return function () {
            return result;
        };
    }
    
    var oneReturner = createConstantFunction(1);  // a function that always returns 1
    var twoReturner = createConstantFunction(2);  // a function that always returns 2
    

    An implementation is allowed to "join" the two functions (see §13.2 of the spec), and if it does so, then oneReturner === twoReturner will be true (see §13.1.2), even though the two functions do different things. Similarly with these:

    // a perfect forwarder: returns a sort of "duplicate" of its argument
    function duplicateFunction(f) {
        return function (f) {
            return f.apply(this, arguments);
        };
    }
    
    var myAlert = duplicateFunction(alert);
    console.myLog = duplicateFunction(console.log);
    

    Here an implementation can say that myAlert === console.myLog, even though myAlert is actually equivalent to alert and console.myLog is actually equivalent to console.log.

    (However, this aspect of ECMAScript 3 was not preserved in ECMAScript 5: functions are no longer allowed to be joined.)

    0 讨论(0)
  • 2021-01-04 13:32

    There are many such functions, here is another example

    function f (a) {
      return a + 1;
    }
    

    1 == "1" but f(1) != f("1")

    This is because equality is a nuanced concept.

    Perhaps more scary is that in your example -0 === +0.

    0 讨论(0)
  • 2021-01-04 13:33

    1/+0 is Infinity and 1/-0 -Infinity, while +0 === -0.

    This can be explained by the fact that ECMA defines -0 to equal +0 as a special case, while in other operations these two values retain their different properties, which result in some inconsistencies.

    This is only possible because the language explicitly defines two non-equal values to be equal, that in fact are not.

    Other examples, if any, should be based on the same sort of artificial equality, and given http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6 there is no other such excention, so probably no other example of this.

    If it's of any use, we can ensure that 0 is not -0 by adding 0 to it:

    var f = function(x) {
       return 1 / (x + 0);
    }
    f(+0) === f(-0)
    
    0 讨论(0)
  • 2021-01-04 13:43

    I'm not so sure this is so scary ;-) Javascript is not a pure language and the presence of +/-0 and the equality of -0 and +0 are specific to IEEE-754 and are "well defined", even if perhaps sometimes surprising. (Even NaN != NaN always being true is well defined, for instance.)

    From signed zero:

    According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators...

    Technically, because the two inputs to f are different, then the result can also be different. For what it's worth, Haskell will treat 0 == -0 as true but will treat (1 / 0) == (1 / (-0)) as false.

    However, I do find this an interesting question.

    Happy coding.

    0 讨论(0)
  • 2021-01-04 13:46

    Yes, because NaN !== NaN.

    var f = function (x) { return Infinity - x; }
    
    Infinity === Infinity // true
    f(Infinity) === f(Infinity) // false
    
    f(Infinity) // NaN
    

    Some other examples that yield NaN whose arguments can be strictly equal:

    0/0
    Infinity/Infinity
    Infinity*0
    Math.sqrt(-1)
    Math.log(-1)
    Math.asin(-2)
    
    0 讨论(0)
  • 2021-01-04 13:46

    this behaviour is perfectly ok, because, in mathematical theory, -0 === +0 is true, and 1/(-0) === 1/(+0) is not, because -inf != +inf

    EDIT: although I am really surprised that javascript can in fact handle these kinds of mathematical concepts.

    EDIT2: additionally, the phenomenon you described is completely based on the fact, that you divide by zero from which you should expect at least some strange behaviour.

    0 讨论(0)
提交回复
热议问题