Public Vars

Back

extend (clj)

(source)

function

(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

Examples

viebel/klipse
(ns clojure.core.rrb-vector.interop
  (:require [clojure.core.rrb-vector.protocols
             :refer [PSliceableVector -slicev
                     PSpliceableVector -splicev]]
            [clojure.core.rrb-vector.rrbt :refer [-as-rrbt]]))

(extend-protocol PSliceableVector
  cljs.core/PersistentVector
  (-slicev [v start end]
    (-slicev (-as-rrbt v) start end))

(extend-protocol PSpliceableVector
  cljs.core/PersistentVector
  (-splicev [v1 v2]
    (-splicev (-as-rrbt v1) v2))
thheller/shadow-cljs
(ns shadow.remote.runtime.cljs.js-builtins
  (:require
    [goog.object :as gobj]
    [clojure.core.protocols :as p]))

(extend-protocol p/Datafiable
  ;; FIXME: this is kind of a bad idea
  ;; can't do this for all objects, since none of the CLJS types implement this
  ;; protocol either. the protocol dispatch will end up using object
  ;; FIXME: this could detect CLJS types to some extent
  ;; or should it just implement the protocols for the types?
  object
  (datafy [o]
    (if-not (identical? (.-__proto__ o) js/Object.prototype)
      o
      (with-meta
        (->> (gobj/getKeys o)
             (reduce
               (fn [m key]
                 (assoc! m key (gobj/get o key)))
               (transient {}))
             (persistent!))
jonase/eastwood
(ns testcases.unusednss3
  (:require [clojure.core.protocols :as protocols]
            [clojure.core.reducers  :as reducers]
            [clojure.data           :as data]
            [clojure.java.io        :as io]
            [clojure.reflect        :as reflect]))

(extend String
  protocols/IKVReduce
  {:kv-reduce (fn [amap f init] nil)})

(extend-protocol reducers/CollFold
  String
  (coll-fold  [coll n combinef reducef] nil))

(extend-type String
  data/EqualityPartition
  (equality-partition [x] nil))
mikera/core.matrix
   Indexes are intended to be used to specify elements, ranges or sub-arrays of core.matrix arrays.
   As such they can be considered as a 1D vector of integer values."
  (:require [clojure.core.matrix.protocols :as mp]
            [clojure.core.matrix.macros :refer [error]])
  (:import [clojure.lang IPersistentVector]))


(extend-protocol mp/PIndexImplementation
  (Class/forName "[J")
	  (index? [m]
      true)
	  (index-to-longs [m]
      m)
	  (index-to-ints [m]
      (int-array m))
	  (index-from-longs [m xs]
      xs)
	  (index-from-ints [m xs]
      (long-array xs))
	  (index-coerce [m a]
      (mp/index-to-longs a)))

(extend-protocol mp/PIndexImplementation
  (Class/forName "[I")
	  (index? [m]
      true)
	  (index-to-longs [m]
      (long-array m))
	  (index-to-ints [m]
      m)
	  (index-from-longs [m xs]
      (int-array xs))
	  (index-from-ints [m xs]
      xs)
	  (index-coerce [m a]
      (mp/index-to-ints a)))

(extend-protocol mp/PIndexImplementation
  IPersistentVector
	  (index? [m]
      (every? integer? m))
	  (index-to-longs [m]
      (long-array m))
	  (index-to-ints [m]
      (int-array m))
	  (index-from-longs [m xs]
      (vec xs))
	  (index-from-ints [m xs]
      (vec xs))
	  (index-coerce [m a]
      (cond
        (mp/index? a)
          (mp/persistent-vector-coerce a)
        (== 1 (long (mp/dimensionality a)))
          (vec (mp/index-to-longs a))
        :else
          (error "Can't make a 1D index from array of shape " (mp/get-shape a)))))
mikera/core.matrix
   WARNING: because they lack efficient indexed access, sequences will perform badly for most
   array operations. In general they should be converted to other implementations before use."
  (:require [clojure.core.matrix.protocols :as mp]
            [clojure.core.matrix.implementations :as imp]
    #?(:clj [clojure.core.matrix.macros :refer [scalar-coerce error]]))
  #?(:clj (:import [clojure.lang ISeq])
     :cljs (:require-macros [clojure.core.matrix.macros :refer [scalar-coerce error]])))

(extend-protocol mp/PImplementation
  ISeq
    (implementation-key [m] :sequence)
    (meta-info [m]
      {:doc "Core.matrix implementation for Clojure ISeq objects"})
    (new-vector [m length]
      (mp/new-vector [] length))
    (new-matrix [m rows columns]
      (mp/new-matrix [] rows columns))
    (new-matrix-nd [m dims]
      (mp/new-matrix-nd [] dims))
    (construct-matrix [m data]
      (mp/coerce-param [] data))
    (supports-dimensionality? [m dims]
      true))

(extend-protocol mp/PIndexedAccess
  ISeq
    (get-1d [m x]
      (scalar-coerce (nth m x)))
    (get-2d [m x y]
      (let [row (nth m x)]
        (mp/get-1d row y)))
    (get-nd [m indexes]
      (if-let [indexes (seq indexes)]
        (if-let [next-indexes (next indexes)]
          (let [mv (nth m (first indexes))]
            (mp/get-nd mv next-indexes))
          (nth m (first indexes)))
        m ;; TODO: figure out if this is a good return value? should it be an error?
        )))

(extend-protocol mp/PIndexedSetting
  ISeq
    (set-1d [m row v]
      (mp/set-1d (mp/convert-to-nested-vectors m) row v))
    (set-2d [m row column v]
      (mp/set-2d (mp/convert-to-nested-vectors m) row column v))
    (set-nd [m indexes v]
      (mp/set-nd (mp/convert-to-nested-vectors m) indexes v))
    (is-mutable? [m]
      false))

(extend-protocol mp/PBroadcast
  ISeq
    (broadcast [m new-shape]
      (mp/broadcast (mp/convert-to-nested-vectors m) new-shape)))

(extend-protocol mp/PBroadcastLike
  ISeq
    (broadcast-like [m a]
      (mp/broadcast (mp/convert-to-nested-vectors a) (mp/get-shape m))))

(extend-protocol mp/PSliceView
  ISeq
    (get-major-slice-view [m i]
      (nth m i)))

(extend-protocol mp/PSliceSeq
  ISeq
    (get-major-slice-seq [m] (vec m)))

(extend-protocol mp/PMatrixRows
  ISeq
    (get-rows [m]
      (vec m)))

(extend-protocol mp/PMatrixColumns
  ISeq
    (get-columns [m]
      (let [m (mp/coerce-param [] m)]
        (mp/get-columns m))))

(extend-protocol mp/PSliceSeq2
  ISeq
    (get-slice-seq [m dimension]
      (let [ldimension (long dimension)]
        (cond
         (== ldimension 0) (mp/get-major-slice-seq m)
         (< ldimension 0) (error "Can't get slices of a negative dimension: " dimension)
         :else (mapv #(mp/get-slice m dimension %) (range (mp/dimension-count m dimension)))))))

(extend-protocol mp/PConversion
  ISeq
    (convert-to-nested-vectors [m]
      (if (> (mp/dimensionality (first m)) 0)
        (mapv mp/convert-to-nested-vectors m)
        (vec m))))

(extend-protocol mp/PDimensionInfo
  ISeq
    (dimensionality [m]
      (inc (mp/dimensionality (first m))))
    (is-vector? [m]
      (== 0 (mp/dimensionality (first m))))
    (is-scalar? [m]
      false)
    (get-shape [m]
      #?(:cljs (js/console.log (str "shape of seq: " m)))
      (cons (count m) (mp/get-shape (first m))))
    (dimension-count [m x]
      (if (== x 0)
        (count m)
        (mp/dimension-count (first m) (dec x)))))

(extend-protocol mp/PFunctionalOperations
  ISeq
    (element-seq [m]
      (if (== 0 (long (mp/dimensionality (first m))))
        m ;; handle 1D case, just return this sequence unchanged
        (mapcat mp/element-seq m)))
    (element-map
      ([m f]
        (mapv #(mp/element-map % f) m))
      ([m f a]
        (let [[m a] (mp/broadcast-compatible m a)]
          (mapv #(mp/element-map % f %2) m (mp/get-major-slice-seq a))))
      ([m f a more]
        (let [[m a & more] (apply mp/broadcast-compatible m a more)] ; FIXME
          (mapv #(mp/element-map % f %2 %3) m (mp/get-major-slice-seq a) (map mp/get-major-slice-seq more)))))
    (element-map!
      ([m f]
        (error "Sequence arrays are not mutable!"))
      ([m f a]
        (error "Sequence arrays are not mutable!"))
      ([m f a more]
        (error "Sequence arrays are not mutable!")))
    (element-reduce
      ([m f]
        (reduce f (mapcat mp/element-seq m)))
      ([m f init]
        (reduce f init (mapcat mp/element-seq m)))))

(extend-protocol mp/PMapIndexed
  ISeq
    (element-map-indexed
      ([ms f]
        (mapv (fn [i m] (mp/element-map-indexed m #(apply f (cons i %1) %&)))
              (range (count ms)) ms))
      ([ms f as]
        (let [[ms as] (mp/broadcast-compatible ms as)]
          (mapv (fn [i m a]
                  (mp/element-map-indexed m #(apply f (cons i %1) %&) a))
                (range (count ms)) ms (mp/get-major-slice-seq as))))
      ([ms f as more]
        (let [[ms as & more] (apply mp/broadcast-compatible ms as more)] ; FIXME
          (mapv (fn [i m a & mr]
                  (mp/element-map-indexed m #(apply f (cons i %1) %&) a mr))
                (range (count ms)) ms
                (mp/get-major-slice-seq as)
                (map mp/get-major-slice-seq more)))))
    (element-map-indexed!
      ([m f]
        (error "Sequence arrays are not mutable!"))
      ([m f a]
        (error "Sequence arrays are not mutable!"))
      ([m f a more]
        (error "Sequence arrays are not mutable!"))))