Skip to content

clojure.core/reify

View this page on ClojureDocs

Type: macro Added: Clojure 1.2 Examples: 8 Runnable: 0
([& opts+specs])

reify creates an object implementing a protocol or interface. 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.

Method heads are recursion points for recur, as in a fn. 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}

Examples

by yasuto on . May have evaluation errors.
by number23 on . May have evaluation errors.
by puredanger on . May have evaluation errors.
by PetrGlad on . May have evaluation errors.
by yubrshen on . May have evaluation errors.
by clojureling on . May have evaluation errors.
by RokLenarcic on . May have evaluation errors.
by huahaiy on . May have evaluation errors.

Note by ieugen

reify can implement multiple interfaces:

(let [a (reify
            java.lang.AutoCloseable
            (close [_this]
              (println "aaa"))
            java.lang.Runnable
            (run [_this]
              (println "Run")))]
    (.close a)
    (.run a))

Note that methods in reify DO NOT accept docstrings like clojure defn's , although they look very similar. You will get compilation error with method not found if you use a docstring.

Something like this

; Evaluating file: java_map.clj
; Syntax error (IllegalArgumentException) compiling reify* at (src/java_map.clj:27:5).
; Can't define method not in interfaces: close
; Evaluation of file java_map.clj failed: class clojure.lang.Compiler$CompilerException

Note by ieugen

Sometimes you will need to add type hints. This is mandatory if there are overloaded methods.

One such case is when implementing java.util.Collection toArray .

Without type hints, you will get

Mismatched return type: toArray, expected: [Ljava.lang.Object;, had: java.lang.Object

A correct way to handle this is like bellow.

Note: when you add one type hint, you need to add for all methods in reify. See docs above.

(reify java.util.Collection
    (^boolean containsAll [_this ^java.util.Collection c])
    (^objects toArray [_this]
      (throw (UnsupportedOperationException.)))
    (^objects toArray [_this ^objects objects]
      (throw (UnsupportedOperationException.))))

https://github.com/clojure/data.avl/commit/03f32144951ab7b50b8a74ea5e8c22629e7fbde0

See also


Content from the matching ClojureDocs page, with authors credited on each contribution.