この機能を使えば、Design By Contract(契約による設計)を容易に実践できます。
事前条件を定義する
さっそく実験してみます。
「パラメータが文字列であること」という事前条件をもつ関数aを定義しました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (defn a [x] {:pre [(instance? String x)]} x) | |
#'user/a | |
user=> (a 1) | |
AssertionError Assert failed: (instance? String x) user/a (NO_SOURCE_FILE:1) | |
user=> (a "123") | |
"123" | |
Assertionを無効にする
Assertionを無効にするには、*assert*へfalseをセットします。
この値はコンパイル時に参照されるため、REPLの場合はdefnを実行する前に設定しておく必要があります。
*assert*へfalseを設定してから、上と同じ関数を定義しました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (set! *assert* false) | |
false | |
user=> (defn a [x] {:pre [(instance? String x)]} x) | |
#'user/a | |
user=> (a 1) | |
1 | |
user=> (a "123") | |
"123" |
例をもう少し
最後に、もう少し実践的な例として日付の比較をする関数を上げておきます。
この関数はCalendar.beforeを呼ぶため、パラメータはCalendarクラスのインスタンスでなければいけません。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (import java.util.Calendar) | |
java.util.Calendar | |
;; 関数定義 | |
user=> (defn before? [base comp] | |
#_=> {:pre [(instance? Calendar base) | |
#_=> (instance? Calendar comp)] | |
#_=> :post [(instance? Boolean %)]} | |
#_=> (.before base comp)) | |
#'user/before? | |
;; 動作確認 | |
user=> (def cal1 (Calendar/getInstance)) | |
#'user/cal1 | |
user=> (def cal2 (Calendar/getInstance)) | |
#'user/cal2 | |
user=> (before? cal1 cal2) | |
true | |
user=> (before? cal2 cal1) | |
false | |
;; Calendar以外を渡してみる | |
user=> (before? 1 2) | |
AssertionError Assert failed: (instance? Calendar base) user/before? (NO_SOURCE_FILE:1) |