On May 27, 2010, at 10:43 PM, Mark S. Miller wrote:

*Given* that we have added egal as a separate reliable non- overloadable operator, I would then have less objection to allowing === to be overloaded. But should we add egal?

I see this as much like the function vs lambda question. I long for a true lambda, as a clean alternative to function. I long for egal, as a clean alternative to ===. However, the argument against lambda is at least as valid as an argument against egal: The functionality represented by lambda or egal is already closely approximated by an existing construct in the language. Adding another similar but subtly different construct to the language adds more confusion and complexity than utility. Imagine how much harder it would be to teach beginning programmers not just about function vs constructors vs methods, but also about these vs lambda. Likewise, imagine teaching beginning programmer not just about === vs ==, but about both of these vs egal.

I agree. We can consider egal on its own, but it did come up last fall when we were discussing value types, in particular whether === is overloadable, even stipulating immutable value types. And something like an identity test would seem to be necessary (as a patch to a mitigate a mistake) if we were to allow === to be overloaded for mutable structs-as-values.

Problem solved by requiring shallowly frozen value types. Which means they cannot be the "structs" we've talked about this week as the array- of-structs alternative to typed array views on a byte buffer. This is the bone of contention Sam and I were gnawing on.


The downside of egal by this argument is just as bad as the downside of lambda. The upside of lambda is much greater than the upside of egal, since === is a much less broken egal than function is a broken lambda.

We've also talked about reforming function, a process begun by ES5 strict mode, which won't culminate in function reaching the TCP nirvana of lambda. But some of us believe that TCP, especially return in a lambda contained by a function returning from the function (or throwing, if the lambda escaped and outlived the function's activation) is a net loss, not a gain.

Digression (bear with me, I hope it is worthwhile):

I wager lambda is attractive to Smalltalk block fans, but Smalltalk does not have first-class methods-as-funargs you can extract and pass around. Alan Kay quote:

"I could hardly believe how beautiful and wonderful the idea of LISP was. I say it this way because LISP had not only been around enough to get some honest barnacles, but worse, there were deep flaws in its logical foundations. By this, I mean that the pure language was supposed to be based on functions, but its most important components -- such as lambda expressions, quotes, and conds -- were not functions at all, and instead were called special forms. Landin and others had been able to get quotes and cons in terms of lambda by tricks that were variously clever and useful, but the flaw remained in the jewel. In the practical language things were better. There were not just EXPRs (which evaluated their arguments), but FEXPRs (which did not). My next questions was, why on Earth call it a functional language? Why not just base everything on FEXPRs and force evaluation on the receiving side when needed?

I could never get a good answer, but the question was very helpful when it came time to invent Smalltalk, because this started a line of thought that said 'take the hardest and most profound thing you need to do, make it great, an then build every easier thing out of it."
[end quote]

This criticism of LISP seems a bit off, insofar as "special form" means only what you can't write as a macro; it does not mean "non- function". LISP lambda as I understand it is based on one definition of "function" (http://en.wikipedia.org/wiki/Lambda_calculus, http://en.wikipedia.org/wiki/Function_%28mathematics%29 -- more learned students of programming languages and foundations of mathematics should jump in if I'm wrong).

What's more, what Kay said about Smalltalk does not seem accurate either: FEXPR^H^H^H^HSmalltalk blocks are not the most profoundly primitive building block (ahem) on which the rest of Smalltalk is built. Messaging and classes are more primitive. Classes with (non- extractable) methods cannot be built on blocks. (Again I hope others more expert than I am will correct me if I'm mistaken.)

Blocks in Smalltalk are brilliant, don't get me wrong. They're just not the most profoundly primitive piece of the language, out of which everything else was built.

I may be misreading Kay -- if he means FEXPRs imply messaging and classes, and sending a message (possibly bearing quoted code as an actual parameter) to a class instance is the most primitive building block, then I agree. But I don't see how FEXPRs imply classes and messaging in full (setting aside blocks for the moment).

Taking all this together, including the loveliness of blocks as message selector arguments for building control structures, it seems to me that lambdas aren't needed in JS, even if you don't find return in a lambda either unwinding an outer function or failing to be confusing and likely to be misused by non-experts. JS has first class functions, which can be used to build classes and many other patterns, at some cost in verbosity and (currently, mitigated by Object.freeze) loss of integrity.

And TCP is not the highest good, or even an unmixed good in a language that did not start out following it, and stick to it the whole way through its evolution.

As Allen has noted, what we miss most about Smalltalk blocks, which seemed attractive at first in the lambda proposal, is the very concise block syntax. This conciseness may yet be achieved, or approximated at any rate, purely via shorthand syntax (http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax ). If we get concise syntax, but not TCP, then lambda is even less attractive.

End of digression. I agree that if given function (with incremental reform under way), JS doesn't need lambda. Given ===, perhaps JS doesn't need egal.

We should talk about egal separately -- it keeps coming up when we turn to value types. It came up when decimal was being proposed for ES3.1 -- remember Object.eq?


That said, I'm not sure I understand why this should gate anything in this thread. Value types should be frozen (shallowly immutable) regardless, or other things break, e.g., they could no longer be transparently passed by copy. C# got this wrong, and paid a semantic complexity price we must avoid. Non-frozen structs should not be value types. Frozen structs could be value types, or could be wrapped in value types or something.

Agreed. Sam?


Given these constraints on mutability and value types, I don't see that it matters whether the reliable comparison is named === or egal.

Quite agreed.

I brought up egal, based on our value types discussion from last fall, to buttress the case against mutable structs as value types. By assuming mutable structs as value types and then showing how they require a true identity relation operator, I hoped to shoot down mutable structs as value types. On second thought, this was not the best way to take on the problems inherent in mutable structs as value types :-P.

C# is an Ecma and ISO standard, but that doesn't mean we should follow it in this regard. In its defense, C#, like C++, is a static language and so can take steps that JS cannot to preserve or recover transparency for features such as pass by value and operator overloading. It is not a good precedent for JS in this regard.


 Btw, please no one suggest that egal be spelled "====". Thanks.

Amen!

/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to