On Oct 7, 2009, at 12:47 AM, Mark Tomko wrote:
This is pretty much what I'd had in mind.
Thanks for the comments and suggestions all.

I don't see how the text of
the Exception is set by the macro, but it'd be really spectacular if
the message were more clear.  Is that message coming from the defvar
form?
The text of the exception was the default one when a validator (http://clojure.org/api#toc518 
) returns logical false. It's customizable by throwing a  
RuntimeException rather than returning logical false.
Here's a new version which addresses this and the other feedback so far:

(defn const-validator
  "Returns a validator that ensures the value of a const never changes"
  [const]
  (fn [x]
    (or (= x @const)
        (throw
         (UnsupportedOperationException.
          (str "the value of const " const " cannot be modified"))))))

(defmacro defconst
"Defines a const: a var whose value is constant. Any attempt to redefine, bind, or set! the const to a different value will throw an exception."
  ([name value]
     `(do
        (defvar ~name ~value)
        (set-validator! (var ~name) (const-validator (var ~name)))
        (var ~name)))
  ([name value doc]
`(defconst ~(with-meta name (assoc (meta name) :doc doc)) ~value)))
With examples:

user=> (defconst e (Math/exp 1))
#'user/e
user=> e
2.7182818284590455
user=> (def e 4)
java.lang.UnsupportedOperationException: the value of const #'user/e cannot be modified (NO_SOURCE_FILE:4)
user=> (binding [e 4] (prn e))
java.lang.UnsupportedOperationException: the value of const #'user/e cannot be modified (NO_SOURCE_FILE:0)
user=> (binding [e e] (prn e))
2.7182818284590455
nil
user=> (binding [e e] (set! e 4))
java.lang.UnsupportedOperationException: the value of const #'user/e cannot be modified (NO_SOURCE_FILE:0)
user=> (defconst my-false false)
#'user/my-false
user=> my-false
false
user=> (def my-false 3)
java.lang.UnsupportedOperationException: the value of const #'user/my- false cannot be modified (NO_SOURCE_FILE:10)
user=> (defconst my-nil nil)
#'user/my-nil
user=> my-nil
nil
user=> (defn my-nil [x] (+ 3 x))
java.lang.UnsupportedOperationException: the value of const #'user/my- nil cannot be modified (NO_SOURCE_FILE:13)
user=>

--Steve

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to