Liking cljdoc? Tell your friends :D

ham-fisted.defprotocol

Alternative protocol implementation.

Major features:

  • Allows subclasses to override only a subset of the methods and if the superclass has overridden the method then the superclasses implementation will be used.

  • Supports primitive typehints on function arguments and return values.

  • Much higher and more predictable multithreaded performance for protocol method invocation due to the fewer number of global variables that are read and written to for a single protocol method invocation. Does not write to global variables on a per-call basis meaning far less cpu/cache traffic in high contention scenarios.

  • Attempting to extend a protocol method that doesn't exist is an error at extension time.

  • Overriding the protocol for the base object array class overrides it for all things convertible to object array while still allowing the concrete array type to match a specific override.

Another design decision is to avoid the interface check - this simplifes the hot path a slight bit at the cost of slightly slower calltimes in the case the interface is used. For those cases often it is possible to simply typehint the interface and call it directly avoiding any protocol dispatch overhead.

Additional call overhead above and beyond a normal fn invocation in an arm mac is -6ns - the time for .getClass call into single concurrent hash map lookup.

Alternative protocol implementation.

Major features:

* Allows subclasses to override only a subset of the methods and if the superclass
has overridden the method then the superclasses implementation will be used.

* Supports primitive typehints on function arguments and return values.

* Much higher and more predictable multithreaded performance for protocol method invocation due to
the fewer number of global variables that are read and written to for a single protocol method
invocation.  Does not write to global variables on a per-call basis meaning far less cpu/cache traffic
in high contention scenarios.

* Attempting to extend a protocol method that doesn't exist is an error at extension time.

* Overriding the protocol for the base object array class overrides it for all things convertible
to object array while still allowing the concrete array type to match a specific override.

Another design decision is to avoid the interface check - this simplifes the hot path a slight bit
at the cost of slightly slower calltimes in the case the interface is used.  For those cases often
it is possible to simply typehint the interface and call it directly avoiding any protocol dispatch
overhead.

Additional call overhead above and beyond a normal fn invocation in an arm mac is `-6ns` - the time
for `.getClass` call into single concurrent hash map lookup.
raw docstring

correct-primitive-fn-typeclj

(correct-primitive-fn-type arg-tags-v method)

defprotocolcljmacro

(defprotocol name & opts+sigs)

A protocol is a named set of named methods and their signatures: (defprotocol AProtocolName

;optional doc string "A doc string for AProtocol abstraction"

;options :extend-via-metadata true

;method signatures (bar [this a b] "bar docs") (baz [this a] [this a b] [this a b c] "baz docs"))

No implementations are provided. Docs can be specified for the protocol overall and for each method. The above yields a set of polymorphic functions and a protocol object. All are namespace-qualified by the ns enclosing the definition The resulting functions dispatch on the type of their first argument, which is required and corresponds to the implicit target object ('this' in Java parlance). defprotocol is dynamic, has no special compile-time effect, and defines no new types or classes. Implementations of the protocol methods can be provided using extend.

When :extend-via-metadata is true, values can extend protocols by adding metadata where keys are fully-qualified protocol function symbols and values are function implementations. Protocol implementations are checked first for direct definitions (defrecord, deftype, reify), then metadata definitions, then external extensions (extend, extend-type, extend-protocol)

defprotocol will automatically generate a corresponding interface, with the same name as the protocol, i.e. given a protocol: my.ns/Protocol, an interface: my.ns.Protocol. The interface will have methods corresponding to the protocol functions, and the protocol will automatically work with instances of the interface.

Note that you should not use this interface with deftype or reify, as they support the protocol directly:

(defprotocol P (foo [this]) (bar-me [this] [this y]))

(deftype Foo [a b c] P (foo [this] a) (bar-me [this] b) (bar-me [this y] (+ c y)))

(bar-me (Foo. 1 2 3) 42) => 45

(foo (let [x 42] (reify P (foo [this] 17) (bar-me [this] x) (bar-me [this y] x)))) => 17

A protocol is a named set of named methods and their signatures:
(defprotocol AProtocolName

  ;optional doc string
  "A doc string for AProtocol abstraction"

 ;options
 :extend-via-metadata true

;method signatures
  (bar [this a b] "bar docs")
  (baz [this a] [this a b] [this a b c] "baz docs"))

No implementations are provided. Docs can be specified for the
protocol overall and for each method. The above yields a set of
polymorphic functions and a protocol object. All are
namespace-qualified by the ns enclosing the definition The resulting
functions dispatch on the type of their first argument, which is
required and corresponds to the implicit target object ('this' in
Java parlance). defprotocol is dynamic, has no special compile-time
effect, and defines no new types or classes. Implementations of
the protocol methods can be provided using extend.

When :extend-via-metadata is true, values can extend protocols by
adding metadata where keys are fully-qualified protocol function
symbols and values are function implementations. Protocol
implementations are checked first for direct definitions (defrecord,
deftype, reify), then metadata definitions, then external
extensions (extend, extend-type, extend-protocol)

defprotocol will automatically generate a corresponding interface,
with the same name as the protocol, i.e. given a protocol:
my.ns/Protocol, an interface: my.ns.Protocol. The interface will
have methods corresponding to the protocol functions, and the
protocol will automatically work with instances of the interface.

Note that you should not use this interface with deftype or
reify, as they support the protocol directly:

(defprotocol P
  (foo [this])
  (bar-me [this] [this y]))

(deftype Foo [a b c]
 P
  (foo [this] a)
  (bar-me [this] b)
  (bar-me [this y] (+ c y)))

(bar-me (Foo. 1 2 3) 42)
=> 45

(foo
  (let [x 42]
    (reify P
      (foo [this] 17)
      (bar-me [this] x)
      (bar-me [this y] x))))
=> 17
raw docstring

extendclj

(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

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
raw docstring

extend-protocolcljmacro

(extend-protocol p & specs)

Useful when you want to provide several implementations of the same protocol all at once. Takes a single protocol and the implementation of that protocol for one or more types. Expands into calls to extend-type:

(extend-protocol Protocol AType (foo [x] ...) (bar [x y] ...) BType (foo [x] ...) (bar [x y] ...) AClass (foo [x] ...) (bar [x y] ...) nil (foo [x] ...) (bar [x y] ...))

expands into:

(do (clojure.core/extend-type AType Protocol (foo [x] ...) (bar [x y] ...)) (clojure.core/extend-type BType Protocol (foo [x] ...) (bar [x y] ...)) (clojure.core/extend-type AClass Protocol (foo [x] ...) (bar [x y] ...)) (clojure.core/extend-type nil Protocol (foo [x] ...) (bar [x y] ...)))

Useful when you want to provide several implementations of the same
protocol all at once. Takes a single protocol and the implementation
of that protocol for one or more types. Expands into calls to
extend-type:

(extend-protocol Protocol
  AType
    (foo [x] ...)
    (bar [x y] ...)
  BType
    (foo [x] ...)
    (bar [x y] ...)
  AClass
    (foo [x] ...)
    (bar [x y] ...)
  nil
    (foo [x] ...)
    (bar [x y] ...))

expands into:

(do
 (clojure.core/extend-type AType Protocol
   (foo [x] ...)
   (bar [x y] ...))
 (clojure.core/extend-type BType Protocol
   (foo [x] ...)
   (bar [x y] ...))
 (clojure.core/extend-type AClass Protocol
   (foo [x] ...)
   (bar [x y] ...))
 (clojure.core/extend-type nil Protocol
   (foo [x] ...)
   (bar [x y] ...)))
raw docstring

extend-typecljmacro

(extend-type t & specs)

A macro that expands into an extend call. Useful when you are supplying the definitions explicitly inline, extend-type automatically creates the maps required by extend. Propagates the class as a type hint on the first argument of all fns.

(extend-type MyType Countable (cnt [c] ...) Foo (bar [x y] ...) (baz ([x] ...) ([x y & zs] ...)))

expands into:

(extend MyType Countable {:cnt (fn [c] ...)} Foo {:baz (fn ([x] ...) ([x y & zs] ...)) :bar (fn [x y] ...)})

A macro that expands into an extend call. Useful when you are
supplying the definitions explicitly inline, extend-type
automatically creates the maps required by extend.  Propagates the
class as a type hint on the first argument of all fns.

(extend-type MyType
  Countable
    (cnt [c] ...)
  Foo
    (bar [x y] ...)
    (baz ([x] ...) ([x y & zs] ...)))

expands into:

(extend MyType
 Countable
   {:cnt (fn [c] ...)}
 Foo
   {:baz (fn ([x] ...) ([x y & zs] ...))
    :bar (fn [x y] ...)})
raw docstring

extendersclj

(extenders protocol)

Returns a collection of the types explicitly extending protocol

Returns a collection of the types explicitly extending protocol
raw docstring

extends?clj

(extends? protocol atype)

Returns true if atype extends protocol

Returns true if atype extends protocol
raw docstring

find-protocol-cache-methodclj

(find-protocol-cache-method protocol cache x)

find-protocol-methodclj

(find-protocol-method protocol methodk x)

It may be more efficient in a tight loop to bypass the protocol dispatch on a per-call basis.

It may be more efficient in a tight loop to bypass the protocol dispatch on a per-call basis.
raw docstring

satisfies?clj

(satisfies? protocol x)

Returns true if x satisfies the protocol

Returns true if x satisfies the protocol
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close