Assemblyscript: comparing strings (difference between == and ===)

Created on 29 May 2019  路  12Comments  路  Source: AssemblyScript/assemblyscript

I'm trying to write some code using assert:

    assert(
        s.toString() === '{W: 20.0, H: 30.0}',
        'toString should be "{W: 20.0, H: 30.0}". Got: "' + s.toString() + '"'
    )

and the assert fails with output showing that the strings are equal (despite failing):

toString should be "{W: 20.0, H: 30.0}". Got: "{W: 20.0, H: 30.0}"

As far as I can tell, the strings look identical (I copy and paste them into JS console, and === shows true).

But if I try to use ==, then I get a runtime error:

output from my abort function:

msg: 0 <-- assert() call in rt/pure.ts has no message
 file: ~lib/rt/pure.ts
 line: 115
 col: 13

Error in console:

Uncaught (in promise) RuntimeError: unreachable
    at wasm-function[19]:41
    at wasm-function[20]:14
    at wasm-function[41]:365
    at wrap (http://127.0.0.1:8080/js/as-loader.js:250:12)
    at runGlas (http://127.0.0.1:8080/ts/index.js:68:9)

Screen Shot 2019-05-29 at 8 35 02 AM

How should I compare the strings?

question

All 12 comments

=== - is compare references. Don't use this especially for strings
== - usual way for compare and trigger overloaded method for string comparision.
This one of things which different compare to JS/TS

So best practice always use ==

Why might I get that error when trying to use ==?

Also what about portability? Seems like this difference between JS/TS and AS loosens the strictness on the JavaScript side, and might increase surface area for bugs?

Maybe == and === should be implemented so they meet expectations?

It's super nice strings are references in AS (as opposed to JS), but I think the expectation here may be important from a DX perspective.

I like the current version of == and === in AS, from a language perspective, but consider what may happen when AS gets more popular: people who may not necessarily be that good at JS yet (or even at programming) may jump onto AS with certain expectations. wdyt?

I keep running into JS code like

        this.width === other.width && this.height === other.height

that I have to convert to

        this.width == other.width && this.height == other.height

which feels odd to some degree because of existing JS/TS habits.

Could it be a source of confusion?

And also, code portability (imagine a module that runs in both AS and TS, but the TS also compiles to plain JS for users that consume the library in plain JS projects).

Doesn't === do the same as == for numeric values?

Oh, does it?

That could be another source of confusion. I'd assumed that I needed == like with strings.

Can it be made consistent with JS/TS? What would be pros/cons?

Tripple equal doesn't any sense in AS, because all types already strictly typed. So === has special meaning (actually using for exact reference comparison)

Copying from the new docs:

AssemblyScript uses === for identity comparisons (means: the exact same object). Idea is that its special JavaScript semantics for strings (same type and value) become irrelevant in a strict type context anyway. Some like this better, some hate it for portability reasons.

var s1 = "1";
var s2 = "123".substring(0, 1);
s1 === s1 // true
s1 === s2 // false
s2 === s2 // true
s1 === 1 // compile error
s1 == s2 // true

Maybe adding:

1 === 1 // true
1 == 1 // true

Really only relevant for strings and possibly operator-overloaded objects.

Btw, the new docs are not finished yet, but if you are interested: https://docs.assemblyscript.org

@MaxGraey
I've been following this project since you posted a message on the thread I started on the TypeScript forum. I think AssemblyScript's handling of == and === is a potentially disastrous language design mistake.

The majority of high quality JS/TS code I've seen used === exclusively and often forbids the use of == via linting rules. By making === something for identity comparisons, you've basically broken compatibility with a _very_ large set of pre-existing TypeScript code. Possibly the case could be made that compatibility with existing code isn't specifically a goal, but the ability to build libraries that are written with a more aggressively typed version of TypeScript, and have these libraries run as WebAssembly or as JS is IMO the main selling point of AssemblyScript.

Because there's no parallel to primitive identity comparisons in TS, this should involve the use of a new operator such as equals or eq or even ====, because any code base that requires primitive identity comparisons isn't going to run in JS anyways, and so compatibility with JS would be an explicit non-goal for this code. Or, if parse compatibility with TS is a goal for some reason, I think some top-level global function like equals(a, b) would be better.

At a minimum, I would reverse the behavior of == and ===. People get fired for using == in JS.

(All this is from the perspective of a person who may have fairly strong grasp of language design, but doesn't claim to know much about AssemblyScript internals & challenges)

Btw, the docs have a mention of the === behavior that might help to clarify the design decision a bit. It's still unfortunate of course and we might want to do something about it, but the reasoning isn't completely off as well. Edit: Sorry, just noticed that this exact comment, just as a quote, exists above already.

@MaxGraey
By making === something for identity comparisons, you've basically broken compatibility with a _very_ large set of pre-existing TypeScript code.

Can this be solved with a simple search and replace?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

solidsnail picture solidsnail  路  5Comments

MaxGraey picture MaxGraey  路  4Comments

DuncanUszkay1 picture DuncanUszkay1  路  3Comments

andy-hanson picture andy-hanson  路  4Comments

emil14 picture emil14  路  3Comments