10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

REPL 駆動開発をしていると困っちゃうことがあるアレコレ

Last updated at Posted at 2016-05-12

Clojure でアプリケーション開発を行なう場合、 REPL を酷使するわけなんですがその中でもハマりやすい問題が幾つかあることに最近同僚を見ていて気付いたので書いておきます。

マルチメソッドが再定義できない

例えば次のようなマルチメソッドを定義していたとします。

(defmulti greeting (fn [time name] time))

(defmethod greeting :morning
  [_ name]
  (str "おはよう、" name))

(defmethod greeting :afternoon
  [_ name]
  (str "こんにちわ、" name))

(greeting :morning "あやぴー") ;;=> "おはよう、あやぴー"
(greeting :afternoon "あやぴー") ;;=> "こんにちわ、あやぴー"

シンプルですね。 ですが、ある気紛れで 2 引数うけとっていたのをマップだけを受け取るようにするために次のように変更したとします。

(defmulti greeting :time)

(defmethod greeting :morning
  [{name :name}]
  (str "おはよう、" name))

(defmethod greeting :afternoon
  [{name :name}]
  (str "こんにちわ、" name))

(greeting {:time :morning :name "あやぴー"}) ;;=> clojure.lang.ArityException
(greeting {:time :afternoon :name "あやぴー"}) ;;=> clojure.lang.ArityException

既に (defmulti greeting (fn [time name] time)) を評価していた後に、 REPL で (defmulti greeting :time) を評価すると nil が返却されると思います。

そして、実際に defmethod などを評価しても問題ないですが、 greeting は引数違いというエラーが出て評価できません。

このケースは何が問題なのか気付き難いのですが、一度 greeting をこのネームスペースから消してあげることで解決できます。こういうときは (ns-unmap *ns* 'greeting) とします。

require して別名を付けていたものを名前を変更して同じ別名をつけたらエラーが出る

ちょっと日本語で説明するのが難しいのですが、以下のようなネームスペースがあったとします。

(ns foo.bar
  (:require [clojure.string :as str]))

str という別名を付けて clojure.stringrequire しています。これを評価した後に次のように書き換えて評価します。

(ns foo.bar
  (:require [clojure.java.io :as str]))
;; => java.lang.IllegalStateException
;;      Alias str already exists in namespace foo.bar, aliasing
;;      clojure.string

str という別名はそのままで clojure.java.iorequire するようにしました( clojure.java.iostr という別名を付けないだろう、っていう突っ込みはなしで)。

このとき例外が吐かれますが、これは分かりやすいですね。単純にその別名は既にこのネームスペースで使われているよ、というだけの話なので (ns-unalias *ns* 'str) としてあげればよいです。

まとめ

Clojure で開発を行なっていると極力 REPL を再起動したくないと思いますが、このように単純に書き直して再評価すればいいというわけではない場合知っていれば対処できますが、知らないと時間を取られてしまいますし REPL を再起動してしまうと思うので転ばぬ先の杖として知っておいてもらえると良いのかなと思います。

他にも思いついたら加筆すると思います。

余談

Emacs(Cider) では C-c C-u(cider-undef) を使うことでどちらのケースでも対応することができます。なので Emacs を使いましょう。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?