Skip to content
Browse files

Adding syntax for constrained records

  • Loading branch information...
1 parent 6c0a505 commit 8c923016293d9a001c47cf42548adeaf4a97afff @fogus fogus committed
Showing with 34 additions and 1 deletion.
  1. +34 −1 src/main/clojure/clojure/core/contracts/constraints.clj
View
35 src/main/clojure/clojure/core/contracts/constraints.clj
@@ -1,7 +1,8 @@
(ns clojure.core.contracts.constraints
(:refer-clojure :exclude [== = not=])
(:use [clojure.core.contracts.impl.utils :only (defcurry-from)])
- (:require [clojure.set :as set]))
+ (:require [clojure.set :as set]
+ clojure.core.contracts.impl.transformers))
;; # constraint functions and multimethods
@@ -74,3 +75,35 @@
(sqr_ 0)
)
+(defmacro defconstrainedfn
+ "Defines a function using the `contract` vector appearing after the arguments.
+
+ (defconstrainedfn sqr
+ [n] [number? (not= 0 n) => pos? number?]
+ (* n n))
+
+ Like the `contract` macro, multiple arity functions can be defined where each argument vector
+ is immediately followed by the relevent arity expectations. This macro will also detect
+ if a map is in that constraints position and use that instead under the assumption that
+ Clojure's `:pre`/`:post` map is used instead.
+ "
+ [name & body]
+ (let [mdata (if (string? (first body))
+ {:doc (first body)}
+ {})
+ body (if (:doc mdata)
+ (next body)
+ body)
+ body (if (vector? (first body))
+ (list body)
+ body)
+ body (for [[args cnstr & bd] body]
+ (list* args
+ (if (vector? cnstr)
+ (second (#'clojure.core.contracts.impl.transformers/build-constraints-description args cnstr (:doc mdata)))
+ cnstr)
+ bd))]
+ `(defn ~name
+ ~(str (:doc mdata))
+ ~@body)))
+

0 comments on commit 8c92301

Please sign in to comment.
Something went wrong with that request. Please try again.