On Jul 3, 2009, at 1:21 AM, Christian Plesner Hansen wrote:

Likewise, for user-defined function foo, foo.prototype is writable -- but not so for built-in constructor functions, and not so for classes as sugar
(more below).

All JS code currently in existence is based on user-defined functions.
For me that is the only case worth considering.  That might explain
the differences in our views.

That's doesn't square with your proposal:

 function pointPlusNumber(a, b) {
   return new Point(a.x + b, a.y + b);
 }

 Function.defineOperator('+', Point, Number, pointPlusNumber);

If you want to amend per Allen's suggestion by imposing fruitless, verbose ".prototype" taxes on the last line, so it reads

Function.defineOperator('+', Point.prototype, Number.prototype, pointPlusNumber);

(or with some other argument order), then what good have you done for users? Unless Point and Number are frozen or otherwise configured in a non-default way, the next line could change one or both .prototype values and make later instances miss the operator.

Sure, that would be a case of "Doctor, it hurts when I do this" (so don't do it), but the same argument applies to instanceof, yet one writes (p instanceof Point), not (p instanceof Point.prototype).

You can't have it both ways. Either mutable .prototype (or mutable function binding, e.g. Point in the global object, or whatever scope it's bound in) is a problem that requires freezing or equivalent lock- down, or it isn't. In any event, there's no reason to impose the .prototype tax, and instanceof-consistency (evolutionary :-P) reason not to.


I'm not a language revolutionary, I prefer gradual evolution.

Your political rhetoric is off target. Classes as sugar are not revolutionary, they build on evolutionary ES3 closures and ES5 Object.freeze and similar features by adding syntactic sugar. They are mostly about "best practices" and "best usability" design defaults for higher-integrity factories than functions called via new can ever be by themselves (due to compatibility).


If you have the option to use a model that works with the existing
language and that integrates well even (that's subjective of course)
why would you limit it to classes or values?

Because we're talking about value types, with that (typeof a == typeof b && a == b) <=> a === b implication extensible to user-defined value types, along with numeric literal syntax.

Value types are new "UI". The benefits won't accrue to user-defined functions as constructors without more opt-in API. And value types deserve first-class syntax, just as classes as sugar do. C# has structs, as Sam pointed out.

Without picking the exact syntax right now, the point remains that we have not been proposing only operators, or even only operators for user-defined constructor functions. We're talking about user-defined value types, ideally with concise, convenient defining as well as invoking syntax.


 The reliance of these
new features on each other will just lead them to become a
language-within-a-language, rather than an evolution of the existing
language.

There are lots of subsets in the language already, this is a teaching and user preference outcome that we can't and shouldn't stop. Multiple paradigms and well-ordered subsets are not a problem, they are a success condition.

But adding operators without considering first-class value types (==/ === and literal syntax) looks like a mistake.


You could, but your proposal nicely avoided noisy ".prototype" expressions
all over, as Allen suggested in reply.

That was a typo.

Why require .prototype noise when instanceof does not? Talk about evolution vs. revolution doesn't justify this break from instanceof's reliance on users to keep their constructor.prototype values intact -- or not, as they please.


If people can live with defining their methods as

Foo.prototype.bar = function () { ... }

That's not the l33t way, of course:

Foo.prototype = {
    bar: function () {...}
    ...
};

But this is noisy and error-prone still, and you are wrong that what one "can live with" should be the last word. People "live with" all sorts of problems in the world, including in JS as it is, and certainly as it was before ES5 (which is definitely not the last word).

Classes as sugar proposes to sweeten such "method definitions", to lighten the boilerplate tax and reduce opportunities for nesting/ bracing/"this"-binding errors.


I think they can live with writing .prototype when defining operators.

Your bikeshed is ugly and overlarge. :-P


In fact I like the uniformity that you have to use the prototype in
both cases.

No uniformity with instanceof, is that incipient revolution?

Perhaps just inconsistency for the sake of low-level explicitness, to be as fair as possible. Or possibly pedantry, but again: if user- defined constructor .prototype references are used and neither the constructor binding in its scope object nor the .prototype property are non-writable and non-configurable, then what is the point?

If the "type" name and .prototype *are* locked down (as with classes as sugar), then there's no good reason for .prototype, it's just a "syn-"tax and an unjustified inconsistency with respect to instanceof.


 Note that library users won't see this, only the library
implementer.  In any case, what users will "cry out for" is
speculation.

We're talking about UI now, so user wishes count. And my bikeshed is prettier and smaller -- I invite others (Tucker can recuse himself ;-) to weigh in.

function "+"(a :Point, b :Number) {
  return new Point(a.x + b, a.y + b);
}

function "+"(a :Number, b :Point) {
  return new Point(a + b.x, a + b.y);
}

function "+"(a :Point, b :Point) {
  return new Point(a.x + b.x, a.y + b.y);
}

I'm not sold on Dylan's \+ (backslashes are troublesome and overloaded), but like quoting, it is a clean extension to the grammar.


Whether or not A's '+' operator uses 'this', it's still a part of A's
behavior and the most consistent place to put it is where A's other
behavior is, its prototype.

Could be, or one could use an optimized multimethod matrix, or some other implementation approach. Again I do not see why the spec should dictate observable prototype properties, internal or otherwise. If it just uses this model but keeps it concealed, then I'm ok with it provided we don't close
the door on multimethods prematurely.

JS allows introspection and self-modification and both are widely used
and cited as advantages of the language.

Self-modification is widely criticized too, even in this thread. See Allen's measured post on Smalltalk history. Monkey-patching bites back, the ability to do it is a mixed blessing.

I chose to make most things mutable in Netscape 2 (even built-in constructor.prototype, if memory serves) because I had too little time to get the core language right, and I knew users would need to monkey- patch. That was then. As noted earlier in this thread, with ES5's Object.freeze etc., it will become harder over time to count on the ability to monkey-patch.


 I would want to extend that
to cover operators as well.

Why? I'm asking for specific use-cases, e.g. one-off or otherwise ad- hoc operator bindings.

You still haven't addressed the ==/=== relation and other "value type" issues such as literal notation extensibility.


Having an internal property with some
associated utility methods on Object is a nice way to get that.

The internal property is invisible to users of the language, and could be replaced by other implementation techniques. That's why I question it as a spec device.

You really did propose symmetric multimethods, but hooked them up "backstage of the language" using "this+" and "+this", etc. At this stage I contend we should focus on the fundamental design elements including multimethods, and not on the ES1-5-style internal property spec hacks.

And of course prettier, more usable bikesheds are fair game, if anyone wants to comment. Operators and other value type extensibility are motivated by usability problems with functions and methods and numeric literals jammed into strings.

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

Reply via email to