1.3.0 permalink Arrow_down_16x16

extend

clojure.core

  • (extend atype & proto+mmaps)
Implementations of protocol methods can be provided using the extend construct:

(extend AType
AProtocol
{:foo an-existing-fn
:bar (fn [a b] ...)
:baz (fn ([a]...) ([a b] ...)...)}
BProtocol
{...}
...)

extend takes a type/class (or interface, see below), and one or more
protocol + method map pairs. It will extend the polymorphism of the
protocol's methods to call the supplied methods when an AType is
provided as the first argument.

Method maps are maps of the keyword-ized method names to ordinary
fns. This facilitates easy reuse of existing fns and fn maps, for
code reuse/mixins without derivation or composition. You can extend
an interface to a protocol. This is primarily to facilitate interop
with the host (e.g. Java) but opens the door to incidental multiple
inheritance of implementation since a class can inherit from more
than one interface, both of which extend the protocol. It is TBD how
to specify which impl to use. You can extend a protocol on nil.

If you are supplying the definitions explicitly (i.e. not reusing
exsting functions or mixin maps), you may find it more convenient to
use the extend-type or extend-protocol macros.

Note that multiple independent extend clauses can exist for the same
type, not all protocols need be defined in a single extend call.

See also:
extends?, satisfies?, extenders

1 Example top

  • ; From Sean Devlin's talk on protocols at Clojure Conj
    (defprotocol Dateable
      (to-ms [t]))
    
    (extend java.lang.Number
      Dateable
      {:to-ms identity})
    
    (extend java.util.Date
      Dateable
      {:to-ms #(.getTime %)})
    
    (extend java.util.Calendar
      Dateable
      {:to-ms #(to-ms (.getTime %))})
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/core_deftype.clj:654 top

(defn extend 
  "Implementations of protocol methods can be provided using the extend construct:

  (extend AType
    AProtocol
     {:foo an-existing-fn
      :bar (fn [a b] ...)
      :baz (fn ([a]...) ([a b] ...)...)}
    BProtocol 
      {...} 
    ...)
 
  extend takes a type/class (or interface, see below), and one or more
  protocol + method map pairs. It will extend the polymorphism of the
  protocol's methods to call the supplied methods when an AType is
  provided as the first argument. 

  Method maps are maps of the keyword-ized method names to ordinary
  fns. This facilitates easy reuse of existing fns and fn maps, for
  code reuse/mixins without derivation or composition. You can extend
  an interface to a protocol. This is primarily to facilitate interop
  with the host (e.g. Java) but opens the door to incidental multiple
  inheritance of implementation since a class can inherit from more
  than one interface, both of which extend the protocol. It is TBD how
  to specify which impl to use. You can extend a protocol on nil.

  If you are supplying the definitions explicitly (i.e. not reusing
  exsting functions or mixin maps), you may find it more convenient to
  use the extend-type or extend-protocol macros.

  Note that multiple independent extend clauses can exist for the same
  type, not all protocols need be defined in a single extend call.

  See also:
  extends?, satisfies?, extenders"
  {:added "1.2"} 
  [atype & proto+mmaps]
  (doseq [[proto mmap] (partition 2 proto+mmaps)]
    (when-not (protocol? proto)
      (throw (IllegalArgumentException.
              (str proto " is not a protocol"))))
    (when (implements? proto atype)
      (throw (IllegalArgumentException. 
              (str atype " already directly implements " (:on-interface proto) " for protocol:"  
                   (:var proto)))))
    (-reset-methods (alter-var-root (:var proto) assoc-in [:impls atype] mmap))))
Vars in clojure.core/extend:
Used in 0 other vars

Comments top

No comments for extend. Log in to add a comment.