<div dir="ltr">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.</div><br><div class="gmail_quote"><div dir="ltr">On Tue, Dec 4, 2018 at 7:25 PM Sultan <<a href="mailto:thysultan@gmail.com">thysultan@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>One way to implement this is as T.J mentioned – using a closure:</div><div><br></div><div>function closure () {</div><div>  var value = 'value'</div><div>  return function (a) { return arguments.length ? value = a : value }</div><div>}</div><div><br></div><div>Another would be to treat functions as the objects they truly are:</div><div><br></div><div>function object () {</div><div><span style="white-space:pre-wrap">      </span>function value (a) { return arguments.length ? this.value = a : this.value }</div><div><span style="white-space:pre-wrap">     </span>value.value = null</div><div>}</div><div><br></div><div>Or as this proposal would allow; <br><br>An idiomatic class-based implementation with a shared callable protocol that is extendable by other classes:</div><div><br></div><div>class prototype {</div><div><span style="white-space:pre-wrap">     </span>[Symbol.callable](...args) { return args.length ? this.value = args[0] : args[0] }</div><div>}</div><div><br></div><div>const a = new prototype()</div><div><br></div><div>assert(a(1) === 1, a() === 1)<br></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Dec 5, 2018 at 1:15 AM Ranando King <<a href="mailto:kingmph@gmail.com" target="_blank">kingmph@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thinking again, this might be a request for static lexical scope variables such that:<div><br></div><div>```js</div><div>function obj() {</div><div>  static value = { test: 42 };</div><div>  return obj.value;</div><div>}</div><div><br></div><div>var a = obj();</div><div>assert(obj() === a);</div><div>```</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Dec 4, 2018 at 4:05 PM Ranando King <<a href="mailto:kingmph@gmail.com" target="_blank">kingmph@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Ok.... maybe I'm thinking a little to literally, but isn't a function already a callable object?<div><br></div><div>```js</div><div>function obj() {</div><div>  return obj.value;</div><div>}</div><div>obj.value = "value";</div><div><br></div><div>assert(obj() === "value");</div><div>```</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Dec 4, 2018 at 1:16 PM Isiah Meadows <<a href="mailto:isiahmeadows@gmail.com" target="_blank">isiahmeadows@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Edit: the wrapper needs to be a function, so ignore that last email. It's wrong.<br>
<br>
-----<br>
<br>
Isiah Meadows<br>
<a href="mailto:contact@isiahmeadows.com" target="_blank">contact@isiahmeadows.com</a><br>
<a href="http://www.isiahmeadows.com" rel="noreferrer" target="_blank">www.isiahmeadows.com</a><br>
<br>
On Tue, Dec 4, 2018 at 2:14 PM Isiah Meadows <<a href="mailto:isiahmeadows@gmail.com" target="_blank">isiahmeadows@gmail.com</a>> wrote:<br>
><br>
> BTW, there are proxies [1], and one of the proxy hooks is to intercept<br>
> calls [2].<br>
><br>
> [1]: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" rel="noreferrer" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy</a><br>
> [2]: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply" rel="noreferrer" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply</a><br>
><br>
> Your "callable object" proposal would be literally as simple as this<br>
> to implement:<br>
><br>
> ```js<br>
> const callable = Symbol.for("callable")<br>
> const handler = {<br>
>     apply(target, thisArg, argsList) {<br>
>         return Reflect.apply(target[callable], thisArg, argsList)<br>
>     },<br>
> }<br>
> function makeCallable(obj) { return new Proxy(obj, handler) }<br>
><br>
> // Your example, ported<br>
> const obj = makeCallable({<br>
>     [callable]: function (...args) { return this[Symbol.for('value')] },<br>
>     [Symbol.for(''value')]: 'value',<br>
> })<br>
><br>
> assert(obj() === 'value')<br>
> obj[callable] = () => 1<br>
> assert(obj() === 1)<br>
> ```<br>
><br>
> -----<br>
><br>
> Isiah Meadows<br>
> <a href="mailto:contact@isiahmeadows.com" target="_blank">contact@isiahmeadows.com</a><br>
> <a href="http://www.isiahmeadows.com" rel="noreferrer" target="_blank">www.isiahmeadows.com</a><br>
> On Tue, Dec 4, 2018 at 12:02 PM Sultan <<a href="mailto:thysultan@gmail.com" target="_blank">thysultan@gmail.com</a>> wrote:<br>
> ><br>
> > Something along the lines of Symbol.iterator protocol for defining callback objects i.e: Symbol.callable:<br>
> ><br>
> > const obj = {<br>
> >     [Symbol.callable]: function (...args) { return this[Symbol.for('value')] },<br>
> >     [Symbol.for(''value')]: 'value',<br>
> > }<br>
> ><br>
> > assert(obj() === 'value')<br>
> > _______________________________________________<br>
> > es-discuss mailing list<br>
> > <a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
> > <a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>