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)

How should I compare the strings?
=== - 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?