Clojure での docstring 挿入位置
defn は一番良く使うので忘れる事はないのだが、他の def 系を使う時に docstring 挿入位置*1ってどうなってたっけと手が止まる事が時々ある。どうも自分の中でイマイチ整理できてないのでここらでちょっとまとめてみた。
基本形
(def ^{:doc " これが基本 "} foo "bar")
色々な def 系
ここで書いているサンプルは基本から派生してメタ情報を明示しなくても入れられるようにできるのかをまず試し、それがダメなら基本形はどうか、と言う流れで試してる。
defn
(defn foo-fn "何かの関数" [] (println "何かの出力")) ;=> #'user/foo-fn
ns
(ns foo.bar "名前空間だよ") nil
defmacro
(defmacro foo-macro "何かのマクロ" [] (println "何かの出力")) ;=> #'user/foo-macro
declare
予想通り declare では派生形はないみたい。
(declare "まだバインドされてない" unbound-var) ;=> ClassCastException java.lang.String cannot be cast to clojure.lang.IObj clojure.core/with-meta (core.clj:214)
基本形は OK。
(declare ^{:doc "まだバインドされてない"} unbound-var) ;=> #'wrap-jfx.core/unbound-var
複数でも基本形が続く場合なら OK。
(declare ^{:doc "まだバインドされてない"} unbound-var ^{:doc "まだまだバインドされない"} unbound-var2) #'user/unbound-var2
defonce
こちらも派生形は使えず。
(defonce once "一度きり" "なんです。") ;=> ArityException Wrong number of args (3) passed to: core$defonce clojure.lang.Compiler.macroexpand1 (Compiler.java:6473)
基本形は OK。
(defonce ^{:doc "一度きり"} once "なんです。") ;=> #'user/once
defprotocol
(defprotocol foo-p "何かのプロトコル") ;=> foo-p
defrecord, deftype
派生形は不可。
(defrecord Foo "何かのレコード" [bar]) ;=> AssertionError No fields vector given. clojure.core/validate-fields (core_deftype.clj:279)
基本形は受け付けはするものの取り出せない。
(defrecord ^{:doc "何かのレコード"} Foo [bar]) ;=> user.Foo (doc Foo) ;=> CompilerException java.lang.RuntimeException: Expecting var, but Foo is mapped to class user.Foo, compiling:
deftype も同様。
;;; プロトコルは前の foo-p を流用 (deftype FooType "何かのタイプ" [bar] foo-p) ;=> AssertionError No fields vector given. clojure.core/validate-fields (core_deftype.clj:279) (deftype ^{:doc "何かのタイプ"} FooType [bar] foo-p) ;=> user.FooType (doc FooType) ;=> CompilerException java.lang.RuntimeException: Expecting var, but FooType is mapped to class user.FooType, compiling:
Java クラス生成絡みでめんどくさいのかね。例外もそんな感じのメッセージ出してるし。
defmulti, defmethod
これは元の defmulti には付けられるが、defmethod には不可。
(defmulti foo-multi "何かのマルチメソッド") ;=> #'user/foo-multi (defmethod ^{:doc "Bar向け"} foo-multi [] "Barメソッド") ;=> CompilerException java.lang.IllegalArgumentException: Parameter declaration Barメソッド should be a vector, compiling:
definline, defstruct, definterface
この辺りは一度も使った事ないし多分この先も使う事がないと思うので未確認。
まとめ
- 全てに派生系が用意されてるわけではない
- 派生形が使える場合は、名前の後に挿入可能
- 一部基本形でも挿入できないものがある
派生系が使えたら派生、使えなかったら基本形と言う形がいいのかも。def が 1.3 で使えるようになった事から今後バージョンアップで対応される、のかな?