Callable objects protocol

Ranando King kingmph at gmail.com
Wed Dec 5 05:02:23 UTC 2018


Ok. I get what you're after. So what's to be gained by being able to make
an object directly callable over simply using functions? I remember that in
C++ there was the concept of a "functor" where overloading `operator()`
would allow you to treat instances as functions, and that had some limited
utility to it (like creating delegate functions). But those use cases are
already easily possible in ES by other means.

On Tue, Dec 4, 2018 at 7:25 PM Sultan <thysultan at gmail.com> wrote:

> Yes function objects are already callable objects. This is meant to allow
> authors the ability to make callable non-function objects with this new
> protocol.
>
> typeof nonFunctionCallableObject === 'object'. As much as Symbol.iterator
> is used to determine if a non-native object is an iterator so too would
> Symbol.callable with regards to non-function callables.
>
> One of the utilities of this can be visualized in the getter/setter type
> callables: fn() gets the value, fn(a) sets the value, this is normally
> supplied with methods to allow an outsider the ability to be reactive to
> changes of the underlining value something akin to observables.
>
> One way to implement this is as T.J mentioned – using a closure:
>
> function closure () {
>   var value = 'value'
>   return function (a) { return arguments.length ? value = a : value }
> }
>
> Another would be to treat functions as the objects they truly are:
>
> function object () {
> function value (a) { return arguments.length ? this.value = a : this.value
> }
> value.value = null
> }
>
> Or as this proposal would allow;
>
> An idiomatic class-based implementation with a shared callable protocol
> that is extendable by other classes:
>
> class prototype {
> [Symbol.callable](...args) { return args.length ? this.value = args[0] :
> args[0] }
> }
>
> const a = new prototype()
>
> assert(a(1) === 1, a() === 1)
>
> On Wed, Dec 5, 2018 at 1:15 AM Ranando King <kingmph at gmail.com> wrote:
>
>> Thinking again, this might be a request for static lexical scope
>> variables such that:
>>
>> ```js
>> function obj() {
>>   static value = { test: 42 };
>>   return obj.value;
>> }
>>
>> var a = obj();
>> assert(obj() === a);
>> ```
>>
>> On Tue, Dec 4, 2018 at 4:05 PM Ranando King <kingmph at gmail.com> wrote:
>>
>>> Ok.... maybe I'm thinking a little to literally, but isn't a function
>>> already a callable object?
>>>
>>> ```js
>>> function obj() {
>>>   return obj.value;
>>> }
>>> obj.value = "value";
>>>
>>> assert(obj() === "value");
>>> ```
>>>
>>> On Tue, Dec 4, 2018 at 1:16 PM Isiah Meadows <isiahmeadows at gmail.com>
>>> wrote:
>>>
>>>> Edit: the wrapper needs to be a function, so ignore that last email.
>>>> It's wrong.
>>>>
>>>> -----
>>>>
>>>> Isiah Meadows
>>>> contact at isiahmeadows.com
>>>> www.isiahmeadows.com
>>>>
>>>> On Tue, Dec 4, 2018 at 2:14 PM Isiah Meadows <isiahmeadows at gmail.com>
>>>> wrote:
>>>> >
>>>> > BTW, there are proxies [1], and one of the proxy hooks is to intercept
>>>> > calls [2].
>>>> >
>>>> > [1]:
>>>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
>>>> > [2]:
>>>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply
>>>> >
>>>> > Your "callable object" proposal would be literally as simple as this
>>>> > to implement:
>>>> >
>>>> > ```js
>>>> > const callable = Symbol.for("callable")
>>>> > const handler = {
>>>> >     apply(target, thisArg, argsList) {
>>>> >         return Reflect.apply(target[callable], thisArg, argsList)
>>>> >     },
>>>> > }
>>>> > function makeCallable(obj) { return new Proxy(obj, handler) }
>>>> >
>>>> > // Your example, ported
>>>> > const obj = makeCallable({
>>>> >     [callable]: function (...args) { return this[Symbol.for('value')]
>>>> },
>>>> >     [Symbol.for(''value')]: 'value',
>>>> > })
>>>> >
>>>> > assert(obj() === 'value')
>>>> > obj[callable] = () => 1
>>>> > assert(obj() === 1)
>>>> > ```
>>>> >
>>>> > -----
>>>> >
>>>> > Isiah Meadows
>>>> > contact at isiahmeadows.com
>>>> > www.isiahmeadows.com
>>>> > On Tue, Dec 4, 2018 at 12:02 PM Sultan <thysultan at gmail.com> wrote:
>>>> > >
>>>> > > Something along the lines of Symbol.iterator protocol for defining
>>>> callback objects i.e: Symbol.callable:
>>>> > >
>>>> > > const obj = {
>>>> > >     [Symbol.callable]: function (...args) { return
>>>> this[Symbol.for('value')] },
>>>> > >     [Symbol.for(''value')]: 'value',
>>>> > > }
>>>> > >
>>>> > > assert(obj() === 'value')
>>>> > > _______________________________________________
>>>> > > 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/20181204/2aaf158b/attachment.html>


More information about the es-discuss mailing list