Error formatting macro: pagetree: java.lang.NullPointerException
Skip to end of metadata
Go to start of metadata
You are viewing an old version of this page. View the current version. Compare with Current  |   View Page History

Problem statement

The actual prototype of js objects is not settable. Thus it's not possible to assign a protocol implementation a live objects, e.g. input from jsonp.

The fields needed to let a javascript object participate in a protocol could simply be assigned, however the algorithm to get the name-mangled protocol fields is woven into extend-type, tighly coupled to target the .protocol property.

Name, Interface?

The operation to extend an instance will be called specify and have an interface similar to deftype. See discussion at CLJS-398

Proposal: CLJS-414

Outline of the implementation

extend-type now expands to specify on the .prototype property.

specify expands to specify* of protocols and method-arity-maps with fn expressions.

Kernel operation: specify*

specify* is loosely based on clojure.core/extend, in that it takes maps of implementing closures.


specify* is needed, because currently CLJS doesn't lift lambdas, so new function objects are allocated every time specify is evaluated. This is fine for specifying prototypes or configuration-object-like protocol instances. It is not so fine for specifying 1000 objects to take part in IEquiv and IHash.

Differences from extend

  • It is a macro
    • bootstrapping: takes a PersistentMap parameter
    • gclosure minification + no reflection layer: clojurescript doesn't know how to access name mangled protocol fields
  • It takes method names as symbols
    • by the time we have an optional reflection layer there might be a cljs.reflect/specify with same interface as extend
  • Takes arities in addition to protocol and method name: (specify* o P {-m {1 m-impl-1, 3 m-impl-3}})
    • OK for a low-level user visible operation??
    • we allow users to implement only parts of a protocol anyway
    • use single-arity fast path
    • no need to unpack single-arity impls from multi-arity fns, which breaks down if user passes javascript fn
    • abstracts protocol name mangling: essentially a setter generator

extend-type refactored: specify

  • Takes fn bodies like extend-type and instantiates them
  • extend-type now just expands to a specify on the .prototype property
  • 'Object' pseudo protocol lives here


  • specify* can't be used with IFn in the current patchset to CLJS-414 as of writing
    • just realized that was a bug, will strike out when fixed
  • specify expects to see each method only once, should error when user tries to do