Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Does Kotlin/JS Return Different Results for === Than Does Kotlin/JVM?

Given this code:

val value = "something"

println(value.toUpperCase().toLowerCase() == value)   // prints true
println(value.toUpperCase().toLowerCase() === value)  // prints false

On Kotlin/JVM 1.3.40, I get:

true
false

On Kotlin/JS 1.3.40, I get:

true
true

I would expect the same results on both, and I would expect the Kotlin/JVM results overall (as I should have different String objects).

Why am I getting different results based on runtime environment?

like image 357
CommonsWare Avatar asked Jul 01 '19 11:07

CommonsWare


People also ask

Is Kotlin interoperable with JavaScript?

Kotlin for JavaScript Kotlin/JS provides the ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies to JavaScript.

Does Kotlin use Java or JavaScript?

Use JavaScript code from Kotlin Kotlin was first designed for easy interoperation with the Java platform: it sees Java classes as Kotlin classes, and Java sees Kotlin classes as Java classes. However, JavaScript is a dynamically typed language, which means it does not check types at compile time.

Is Kotlin JS stable?

It is almost stable, but migration steps may be required in the future. We'll do our best to minimize any changes you have to make. The Kotlin/JS IR compiler backend is the main focus of innovation around Kotlin/JS, and paves the way forward for the technology.

Is Kotlin similar to JavaScript?

Of course Kotlin and java have very much in common but I was surprised to find its similarities with Javascript. I was able to relate many concepts of Kotlin with that of Javascript and it made my learning much easier. In this article I am sharing some features and concepts that are common to both Kotlin & Javascript.


2 Answers

This is because of how the runtime handles it.

On the JVM, == maps to equals, and === maps to == (identity checking), as outlined here. Meanwhile, JavaScript's equals operators are weirder. If you decompile your code, you get this with JS:

kotlin.kotlin.io.output.flush();
if (typeof kotlin === 'undefined') { 
    throw new Error("Error loading module 'moduleId'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'moduleId'."); 
}
var moduleId = function (_, Kotlin) { 
    'use strict'; 
    var equals = Kotlin.equals; 
    var println = Kotlin.kotlin.io.println_s8jyv4$; 
    function main(args) { 
        var value = 'something';
        println(equals(value.toUpperCase().toLowerCase(), value)); // NOTE: equals
        println(value.toUpperCase().toLowerCase() === value);      // NOTE: ===
    } 
    _.main_kand9s$ = main; 
    main([]); 
    Kotlin.defineModule('moduleId', _); 
    return _; 
}(typeof moduleId === 'undefined' ? {} : moduleId, kotlin); 
kotlin.kotlin.io.output.buffer;

Now, if you consider the equivalent Java code (slightly shortened and without Kotlin):

public static void main(String[] args){
    String value = "something";

    System.out.println(value.toUpperCase().toLowerCase().equals(value));
    System.out.println(value.toUpperCase().toLowerCase() == value);
}

toUpperCase().toLowerCase() creates a new object, which breaks the == comparison, which is identity checking.

While === is outlined as identity checking as well, a === b is true if a and b are strings that contain the same characters. As you can tell from the decompiled Kotlin code, Kotlin.JS compiles to primitive Strings, not String objects. Because of that, the === in JS will return true when you're dealing with primitive strings.

like image 134
Zoe stands with Ukraine Avatar answered Sep 20 '22 19:09

Zoe stands with Ukraine


In JavaScript there are both primitive strings and string objects (see e.g. "Distinction between string primitives and String objects" in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).

value.toUpperCase().toLowerCase() === value in Kotlin/JS compiles to value.toUpperCase().toLowerCase() === value in JavaScript (as you can verify by looking at the "Generated JavaScript code" tab at https://try.kotlinlang.org/). value.toUpperCase().toLowerCase() returns a primitive string. === on primitive strings is normal equality.

like image 39
Alexey Romanov Avatar answered Sep 21 '22 19:09

Alexey Romanov