Why can't objects be callable?

Dean Landolt dean at deanlandolt.com
Wed Mar 7 08:58:32 PST 2012


On Wed, Mar 7, 2012 at 8:53 AM, Russell Leggett
<russell.leggett at gmail.com>wrote:

> On Wed, Mar 7, 2012 at 2:58 AM, David Bruant <bruant.d at gmail.com> wrote:
>
>> Le 07/03/2012 02:10, Brandon Benvie a écrit :
>> > I start this coming from the standpoint of an honest question that I
>> > don't know the answer to: is there a specific reason that objects
>> > can't be callable in js? Aside from the "that's just how the language
>> > is" answer, I was wondering if there's some other computer sciency or
>> > performance reason for the restriction.
>> One further detailled explanation of "that's just how the language work"
>> would be that a JavaScript invariant is that a value has a stable result
>> to "typeof". So it's impossible to change a non-callable object into a
>> callable object without breaking this invariant (as stated by ES5, a
>> callable object has "function" for it's typeof value while non-callable
>> objects have "object").
>>
>
> Scala has a notion of "extractor" objects:
> http://www.scala-lang.org/node/112 – with the right method signatures,
> they can be used like a function, or be used in pattern matching (or for
> us, destructuring only - for now). I can see how this would be useful, and
> could be achieved using private names instead of method signatures. The
> result would be an object that could still be typeof "object" and also
> callable.
>
>     import {apply,unapply} from "@extractor";
>
>     const Twice = {
>         [apply]:function(x){
>             return x * 2;
>         },
>         [unapply]:function(z){
>             return z%2 == 0? z/2 : null;
>         }
>     }
>
>     let x = Twice(21);    // x == 42
>     let Twice(n) = x; // n == 21
>
> I think the unapply half could be useful in destructuring, though I think
> it would be distinctly more useful in pattern matching (which I would love
> to see included). Or the unapply half could just be dropped if too
> problematic.
>

<3

Of course, we'd need a completely different pattern for duck-testing
callables. If functions were re-specified to include the `apply` private
name then testing for its presence may be enough. This would fall down in
the face of naive iframe-sandboxing -- is this a big problem? If so, at
worst sandboxes could use a proxy to alias the various apply brands (I
suspect there's a lighter weight strategy that could work too -- I only say
this to note the benefits of using brands for psuedo-typing).



>
>> Besides this, I don't see a restriction on why you couldn't just use
>> functions each time you need an object.
>>
>>
> The biggest restriction would probably just be forcing the way you have to
> create it. It has to start life as a function and get modified from there.
>
> - Russ
>
>
>>
>>
>> > I've had this question a number of times but the most recent spart was
>> > seeing this from Allen Wirfs-Brock:
>> >
>> >>  //define a non constructible superclass that provides some
>> Smalltalk-like conventions
>> >>  const AbstractClass = Function.prototype <| {
>> >>    subclassResponsibility() {throw new Error(this.name+" did not
>> implemented an abstract method")},
>> >>    shouldNotImplement() {throw new Error(this.name+" should not
>> implemented by "+this.name)},
>> >>    name: "AbstractClass",
>> >>    prototype: Object.prototype <|{
>> >>      get class() {return this.constructor},
>> >>      error(message) {throw new Error(message)},
>> >>      subclassResponsibility() {return
>> this.class.subclassResponsibility()},
>> >>      shouldNotImplement() {return this.class.shouldNotImplement()},
>> >>      errorSubscriptBounds(index) {this.error("subscript is out of
>> bounds: "+index)}
>> >>    }
>> >>  };
>> > As it is currently, the behavior of a function is that it defaults to
>> > be a `constructor-like`. It has a prototype that it bestows upon
>> > objects JS tells it to create, and it's not even possible for it to
>> > have no prototype property. I would imagine a callable object is more
>> > like a non-constructor function (something like isNaN) or, currently,
>> > it's essentially the same as doing `object.valueOf()`. In fact there's
>> > nothing stopping one from making every single object they use (aside
>> > from an array) callable simply by starting with a function literal and
>> > assigning its __proto__.
>> However, you do not need to use functions as constructors.
>> I wish block lambda [1] to be adopted for ES6. I think they would fit
>> your vision of functions, because it certainly wouldn't make sense to
>> construct with them and they would certainly have no use of a
>> 'prototype' property.
>>
>> Hopefully, it will be possible to combine block-lambda with the <|
>> operator to create callable objects with arbitrary prototype.
>>
>> > (...)
>> > Partilly this is resolved with ES6, as is the arraylikes problem.
>> Indeed. All the "change the prototype at object creation time" was the
>> rational behind the <| operator (and as you note, it will work for
>> arrays, and functions and most things)
>>
>> David
>>
>> [1] http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120307/50c53294/attachment.html>


More information about the es-discuss mailing list