callable objects ?

Brendan Eich brendan at mozilla.org
Wed Apr 11 11:54:56 PDT 2012


Michael Fogus wrote:
> I know some things about ClojureScript and would be happy to answer
> any direct questions. However, I think its notion (and Clojure proper)
> is that "functions are data are functions" is very powerful.

It's a great idea (I first met John McCarthy in 1977 when I was 16). Too 
bad JS was not allowed to be "Scheme in the browser".

>   A lot of
> interesting patterns fall out of this as others have pointed out.

I'm ready to jump in with both feet, except for JS's age and the 
possibility that too much code on the web counts on things like

(typeof x == "function") <=> x() works and x.apply is the expected built-in

No problem, you say, we can leave typeof alone and add a callable 
predicate and evangelize that. Ok, provided the callable protocol uses 
an ES6 private name (think gensym), any public name could be in use and 
make a false positive when testing callability.

So let's use a well-known private (unique, should say) name, e.g.

module std {
   ...
   export const invokeName = Name.create("invoke");

   export function callable(v) {
     if (typeof v == "function")
       return true;
     if (typeof v == "object" && v != null)
       return invokeName in v; // could be pickier but let's start here
     return false;
   }
}

// make an object obj be callable:
obj[invokeName] = function (...args) { /* ... */ };

Looks ok, ignoring details such as how the client code gets the standard 
unique name binding (import invokeName from "@std" or some such).

One can't assume apply or call or other Function.prototype heritage is 
in x just because callable(x) returns true. Callability is wider and 
weaker than typeof-result "function".

IIRC, security conscious folks do not want an attacker to be able to 
make any old object callable. Cc'ing Mark for his thoughts.

/be


More information about the es-discuss mailing list