store/[org.clojure/clojure "1.8.0"] clj::clojure.core/reify

Community Documentation

Edit

Arities

[& opts+specs]

Docstring

Reify is a macro with the following structure:

(reify options* specs*)

Currently there are no options.

Each spec consists of the protocol or interface name followed by zero or more method bodies:

protocol-or-interface-or-Object
(methodName [args+] body)*

Methods should be supplied for all methods of the desired protocol(s) and interface(s). You can also define overrides for methods of Object. Note that the first parameter must be supplied to correspond to the target object ('this' in Java parlance). Thus methods for interfaces will take one more argument than do the interface declarations. Note also that recur calls to the method head should not pass the target object, it will be supplied automatically and can not be substituted.

The return type can be indicated by a type hint on the method name, and arg types can be indicated by a type hint on arg names. If you leave out all hints, reify will try to match on same name/arity method in the protocol(s)/interface(s) - this is preferred. If you supply any hints at all, no inference is done, so all hints (or default of Object) must be correct, for both arguments and return type. If a method is overloaded in a protocol/interface, multiple independent method definitions must be supplied. If overloaded with same arity in an interface you must specify complete hints to disambiguate - a missing hint implies Object.

recur works to method heads The method bodies of reify are lexical closures, and can refer to the surrounding local scope:

(str (let [f "foo"] 
     (reify Object 
       (toString [this] f))))
== "foo"

(seq (let [f "foo"] 
     (reify clojure.lang.Seqable 
       (seq [this] (seq f)))))
== (\f \o \o))

Reified objects always implement clojure.lang.IObj and the reify form transfers meta data of the form to the created object.

(meta ^{:k :v} (reify Object (toString [this] "foo")))
== {:k :v}

Source

(defmacro reify 
  "reify is a macro with the following structure:

 (reify options* specs*)
  
  Currently there are no options.

  Each spec consists of the protocol or interface name followed by zero
  or more method bodies:

  protocol-or-interface-or-Object
  (methodName [args+] body)*

  Methods should be supplied for all methods of the desired
  protocol(s) and interface(s). You can also define overrides for
  methods of Object. Note that the first parameter must be supplied to
  correspond to the target object ('this' in Java parlance). Thus
  methods for interfaces will take one more argument than do the
  interface declarations.  Note also that recur calls to the method
  head should *not* pass the target object, it will be supplied
  automatically and can not be substituted.

  The return type can be indicated by a type hint on the method name,
  and arg types can be indicated by a type hint on arg names. If you
  leave out all hints, reify will try to match on same name/arity
  method in the protocol(s)/interface(s) - this is preferred. If you
  supply any hints at all, no inference is done, so all hints (or
  default of Object) must be correct, for both arguments and return
  type. If a method is overloaded in a protocol/interface, multiple
  independent method definitions must be supplied.  If overloaded with
  same arity in an interface you must specify complete hints to
  disambiguate - a missing hint implies Object.

  recur works to method heads The method bodies of reify are lexical
  closures, and can refer to the surrounding local scope:
  
  (str (let [f \"foo\"] 
       (reify Object 
         (toString [this] f))))
  == \"foo\"

  (seq (let [f \"foo\"] 
       (reify clojure.lang.Seqable 
         (seq [this] (seq f)))))
  == (\\f \\o \\o))
  
  reify always implements clojure.lang.IObj and transfers meta
  data of the form to the created object.
  
  (meta ^{:k :v} (reify Object (toString [this] \"foo\")))
  == {:k :v}"
  {:added "1.2"} 
  [& opts+specs]
  (let [[interfaces methods] (parse-opts+specs opts+specs)]
    (with-meta `(reify* ~interfaces ~@methods) (meta &form))))

Example 1

Edit
(ns foo)

;;; This is a library for the shopping result.

(defrecord Banana [qty])
(defrecord Grape  [qty])
(defrecord Orange [qty])

;;; 'subtotal' differs from each fruit.

(defprotocol Fruit
  (subtotal [item]))

(extend-type Banana
  Fruit
  (subtotal [item]
    (* 158 (:qty item))))

(extend-type Grape
  Fruit
  (subtotal [item]
    (* 178 (:qty item))))

(extend-type Orange
  Fruit
  (subtotal [item]
    (* 98 (:qty item))))

;;; 'coupon' is the function returing a 'reify' of subtotal. This is
;;; when someone uses a coupon ticket, the price of some fruits is 
;;; taken off 25%.

(defn coupon [item]
  (reify Fruit
    (subtotal [_]
      (int (* 0.75 (subtotal item))))))

;;; Example: To compute the total when someone bought 10 oranges,
;;;  15 bananas and 10 grapes using a coupon.
;;; foo=> (apply +  (map subtotal [(Orange. 10) (Banana. 15) (coupon (Grape. 10))]))
;;; 4685            ; (apply + '(980 2370 1335))
;;; foo=> 

Example 2

Edit
;;;; This example shows how to reify a multi-arity protocol function
;;;; (note the different style in defprotocol vs reify)

;; define a multi-arity protocol function blah
(defprotocol Foo
  (blah
    [this x]
    [this x y]))

;; define an anonymous extension via reify
(def r (reify Foo 
         (blah [_ x] x)
         (blah [_ x y] y)))

;; invoke blah via the r instance
(blah r 1)   ;; => 1
(blah r 1 2)   ;; => 2


Example 3

Edit
;; Using a reified FileFilter implementation to obtain only directory files
(.listFiles (java.io.File. ".")
            (reify
              java.io.FileFilter
              (accept [this f]
                (.isDirectory f))))

Uses on crossclj