Language design

# KOLANICH (9 years ago)

Hello all. I have opened the page developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla and was horrified. What happened with JS? Why do we need all this methods? Why a lot of functionality is now doubled, and a lot of new badly designed API and language features was introduced?

I understand the word "compatibility", but I think that no compatibility worth enough to be preserved sacrificing the language design making it self-contradictary. For example, Object.is compares identity. Operator === also compares identity but in a bit differrent way. Why not just make == check equality only between compatible types, === check identity (that the object is the same) and throw out Object.is.

Operator [] casts its argument to string ... but not when used with Symbol (why not just allow the key to be any object and match using ===). New iterator API relyes on Symbol.iterator. Why do we need it? Why not just use strings and prototypes? fromCodePoint doubles fromCharCode, but differs a bit. Why didn't you repurpose fromCharCode, just allowing it to take a string arguments describing codepages?

Iterability and enumerability are distinct, but iterability is just enumerability with numeric key (yeah, I know that it is possible to create endless or random iterator, but in fact this means that you just don't need to use the key provided). Why there is iterability, but not enumerability with properties of iterability and enumerability united? Why we need enumerability to make it work with for ... in and iterability to make it work with for ...  of?

Why can't we use methods definitions to define methods as a function declaration? Why JS is so badly designed?

# Kevin Smith (9 years ago)
# Edwin Reynoso (9 years ago)

Yes please edit it, you don't have to repost. BTW the only thing I can agree with is the Object.is() which to me seems like the only problem it solves is Object.is(NaN, NaN) now returns true

# Brendan Eich (9 years ago)

Edwin Reynoso wrote:

Yes please edit it, you don't have to repost. BTW the only thing I can agree with is the Object.is() which to me seems like the only problem it solves is Object.is(NaN, NaN) now returns true

You didn't agree with the root post (whose sender has had the "mod" flag set for moderated postings, btw). That root post ignored compatibility constraints that have been discussed to death over the years, and just glibly asserted that == and === could be changed. So, I don't believe you agreed with that noise. Am I mistaken?

If your point is that Object.is does not pull its weight, make a stronger case for why people should have to write it by hand.

You missed that Object.is(-0, +0) (and with arguments transposed) is false, while -0 === +0.

# KOLANICH (9 years ago)

You missed that Object.is(-0, +0) (and with arguments transposed) is false, while -0 === +0.

No. I really think that -0 === +0 also should be false, because they are different objects. So should be 0=="0". I don't think it will break a lot of code, because I cannot mind a situation where such comparisons can be needed (except comparing zIndex and other numeric attributes casted to strings automatically, but it is not very hard to insert parseFloat there).

If your point is that Object.is does not pull its weight

My point is that there shouldn't not be a lot of similar API which behavior is not intuitively clear. I don't know what you think about it, but I think that this should have semantics of comparison by value. We can compare numbers, so let 3.0==3 be true. A string and a number have different semantics (string is array of characters, number is number), so let 3=="3" be false. Also ({a:1}=={a:1}) should be true; undefined==undefined should be true; null==null should be true;NaN== NaN should be false; Number.POSITIVE_INVINITY==Number.POSITIVE_INVINITY should be false. === has identity semantics undefined===undefined shoulld be true; null===null should be true;NaN=== NaN should be true; Number.POSITIVE_INVINITY===Number.POSITIVE_INVINITY should be true because they all in fact a special value. -0==+0 should be true, because it is the same number. -0===+0 should be false because they are different values (which in case of integer can be understood as differrent objects of class Number).

And again, I don't think that someone strongly relies on current semantics of comparison because of its counterintuitivity. Behaving the described way we only need the two operators.

Пятница, 12 июня 2015, 16:45 -07:00 от Brendan Eich <brendan at mozilla.org>:

Edwin Reynoso wrote:

Yes please edit it, you don't have to repost. BTW the only thing I can agree with is the Object.is() which to me seems like the only problem it solves is Object.is(NaN, NaN) now returns true

You didn't agree with the root post (whose sender has had the "mod" flag set for moderated postings, btw). That root post ignored compatibility constraints that have been discussed to death over the years, and just glibly asserted that == and === could be changed. So, I don't believe you agreed with that noise. Am I mistaken?

If your point is that Object.is does not pull its weight, make a stronger case for why people should have to write it by hand.

You missed that Object.is(-0, +0) (and with arguments transposed) is false, while -0 === +0.

/be


es-discuss mailing list es-discuss at mozilla.org, mail.mozilla.org/listinfo/es-discuss



# Benjamin Gruenbaum (9 years ago)

I'm going to address your questions.

Object.is - have you checked and read the actual thread in the list explaining the motivation behind that?

"Operator [] casts its argument to string ... but not when used with Symbol" - that's the poit of symbols - to have non string keys that are unique. Reading the motivating symbol thread or a tutorial should clarify the point of symbols and how they solve a hard problem in a rather elegant way. Also it's not an operator.

"New iterator API relyes on Symbol.iterator. Why do we need it? " - to have a uniform way to iterate things that support iterations, much like implementing an interface in a statically typed language or iter in Python. Again, this has been explained a few times in past threads.

" Why not just use strings and prototypes?" - because that would break backwards compatibility and be a less elegant solution, using a symbol also ensures you do not accidentally implement a protocol.

"fromCodePoint doubles fromCharCode, but differs a bit. " it differs a lot. Not that it would matter much since you can't break the whole internet just because you'd like to "repurpose" something. Code that relies on this is literally used by billions of people and billions of websites.

"Iterability and enumerability are distinct, but iterability is just enumerability with numeric key (yeah, I know that it is possible to create endless or random iterator, but in fact this means that you just don't need to use the key provided)." - in the scope of the spec enumerability is of object keys and iterability is iteration of an iterator. Not everything has its keys iterated - the reason an iteration protocol is needed is to make this distinction - how would you iterate a Map or a Set or any other non array-or-object collection? This is why every other language defines this form of protocol (From c++ to Java and C# and Scala to dynamic languages like Python to purely functional ones like Erlang and Haskell) and why ES does too.

" Why can't we use methods definitions to define methods as a function declaration?" I have no idea what you were trying to say here, sorry.

"Why JS is so badly designed?" for the same reason other languages are. JS has quite the back story, a lot of baggage and hindsight is always 20/20. Every language sells you the "awesome" story until you use it - I'd argue other languagesl like Python and Haskell have as much if not more baggage. Ignoring the fact asking this is completely pointless and needlessly argumentative - language design is really hard. If you're interested in what motivated a lot of the things in ES - please the material is out there go read it :)

# Boris Zbarsky (9 years ago)

On 6/12/15 8:21 PM, KOLANICH wrote:

No. I really think that -0 === +0 also should be false, because they are different objects. So should be 0=="0". I don't think it will break a lot of code

Theory is great, but experiment is better.

With that in mind, I have created a build of Firefox 38 that you can try that has just your proposed modification for ==: test false when one side is a string and the other is a number. Making -0 === +0 test false would take more effort than I'm willing to put in right now, since the JITs actually optimize that path, unlike the other one, and I'd have to change the actual low-level assembly used in a pretty nontrivial (e.g. ucomisd treats 0 and -0 as equal so I'd need to add manual tests for 0 vs -0).

In any case, you can try this build out and report back on whether you find any problems on websites.

You can download the test builds at one of the following links, depending on which one you want:

ftp.mozilla.org/pub/mozilla.org/firefox/try-builds/[email protected]/try-linux/firefox-38.0.6.en-US.linux-i686.tar.bz2, ftp.mozilla.org/pub/mozilla.org/firefox/try-builds/[email protected]/try-linux64/firefox-38.0.6.en-US.linux-x86_64.tar.bz2, ftp.mozilla.org/pub/mozilla.org/firefox/try-builds/[email protected]/try-win32/firefox-38.0.6.en-US.win32.zip

The Mac build is still in progress, but should appear in ftp.mozilla.org/pub/mozilla.org/firefox/try-builds/[email protected]/try-macosx64 in a few hours I expect.

-Boris

P.S. I've encountered at least one site in the past week that relied on string vs number == just triaging bug reports. So I'm not too hopeful about your chances of avoiding problems with this build, but I figure you should give it a shot at least.

# KOLANICH (9 years ago)

I have tested Boris's build The results are:

  • chrome is broken in large part
  • Mail.ru mail interface is broken
  • Gmail is broken
  • google docs is broken
  • peacekeeper is not broken
  • 3 russian it news portals are not broken (UI is OK, on the one sending the comment worked with minor bug in UI, but when I tried one more time, it disappeared, so maybe not 3 but 2)
  • Google is partly broken
  • Microsoft.com is not broken
  • mail.live.com is broken
  • mail.yandex.ru is broken
  • reddit is not broken (I havent tested send)
  • facebook is broken

Probably this is because of JQuery, my projects (I don't use JQuery in them) work fine.

# joe (9 years ago)

Heh, I remember I thought many ES6 features were oddly designed, or even crazy. However, since I was dealing with production code and needed said features (and had decided to target ES6), I dutifully added 'em to my crappy transpiler one-by-one.

Now I think I was crazy. When I was implementing the module import/export syntax, I couldn't fathom why anyone would design it that way. Now I can't imagine living without it; I love it. I thought the concept of Symbol was odd too, until I got sick of seeing iterator everywhere (that horrible "__" gets hard on the eyes after a while).

When I first started by project (all-shape.com), my code looked like this:

function Class() {
    Object.defineProperty(this, "prop", {
        get : function() {
        }
    })
}
Class.prototype.MethodA = function() {
}
Class.prototype.MethodB = function() {
}

You have no idea how much it meant to me when I implemented classes and started seething this instead:

class Class {
    MethodA() {
    }
    MethodB() {
    }
    get prop() {
    }
}

Believe it or not, I implemented super() late. Oh man. When I started seeing suff like:

Bleh.prototype.bleh.call(this)

Replaced with:

super.bleh();

I thought I would jump for joy.

Anyway, I'm incredibly grateful to the TC39 committed for their work.

Thanks, Joe

P.S.

. . .If a mailing list must have noise a well as signal, why not have positive noise mixed in with the negative?

# Wes Garland (9 years ago)

That root post ignored compatibility constraints that have been discussed to death over the years, and just glibly asserted that == and === could be changed.

The last time == and === were changed (JS 1.1-1.2-1.3) I was a pretty green developer building a very large DHTML application. I lost many nights of sleep trying to figure out why my code worked on one version of Netscape but not the other. You can't change stuff like that, we have paid the price to learn that lesson!

The OP also spoke about fromCodePoint vs fromCharCode. It is necessary, IMO, to be able to manipulate both the underlying bytes and Unicode. I bumped into a related issue on our Server Side solution this week, importing malformed UTF8. Our platform has a big switch which changes how we handle C strings, and both modes of operation were necessary to analyze and resolve the problem.

I'm looking forward to upgrading to ES6. I'm building large, somewhat complex, applications that share ES5 libraries and data on the browser and server. I am looking forward to features like default parameters, destructuring assignment (we have this in the server and like it), better modules (although there will be migration pain), and template strings.

I'm sure there will be stuff I don't need - but that's okay, I just won't use it.