Skip to content

Instantly share code, notes, and snippets.

@ianrumford
Created November 15, 2012 16:08
Show Gist options
  • Save ianrumford/4079419 to your computer and use it in GitHub Desktop.
Save ianrumford/4079419 to your computer and use it in GitHub Desktop.
Contracts examples blog_make_inline_functions1
(ns contracts-examples.blog_make_inline_functions1
(:require [clojure.core.contracts :as ccc]))
;; Generate output contract - note the signature accepts anything
;; Require my modification to clojure.core.contracts
(def aspect-spit-a-number
(ccc/contract aspect-spit-a-number-cx
"enforce a number as the return value"
[& any]
[(report-parms any) => (instance? Number %)]))
;; Red tape function to perform call to the target function
(defn inline-contract-execute-function
"Execute the function specified in the call"
[args]
(let [[f & rest] (first args)
ret (apply f rest)]
(println "inline-contract-execute-function: <> ret" (class ret) ret "f" (class f) f "rest" (class rest) rest)
ret
))
(defmacro make-inline-contract-functions
"Sugar to generate inline fucntiosned constrained by contracts
For example:
(enforce-this-contract my-function my-function-args)
Args to this macro: a sequence of vectors, each having
1. k-mn - name of the contract function to create e.g. enforce-this-contract
2. k-cx - 0, 1 more contracts to apply (using with-constraints)
Generates an anonymous function to call my-function with parameters my-function-args
Then applies the contracts using with-constraints
"
[& kontracts-vecs]
(let [kontracts (for [[k-mn & k-cx] kontracts-vecs]
(let [k-na (name k-mn)
k-sm (symbol k-na)
;;k-ds (str "the contract for " (name k-mn))
k-fa (symbol (str k-na "-fn"))
;;k-fn identity
k-fn (list `fn k-fa '[& args] (list `inline-contract-execute-function 'args))
k-ct (list* `ccc/with-constraints k-fn k-cx)
k-df (list 'def k-sm k-ct)
]
[k-na k-df]))]
`(do
~@(for [[_ c#] kontracts] c#)
nil)))
;; Create the contract with signature expecting target function and optional arguments
(make-inline-contract-functions
[:inline-spits-a-number aspect-spit-a-number])
;; Will succeed - the trivial case
(inline-spits-a-number identity 5)
;; Will succeed
(inline-spits-a-number reduce + [1 2 3 4 5])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment