Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

"A downside is that the compiler won't warn you if you break some constraint that invalidates the model of whatever the map is meant to represent. For example, if you remove a value from the map necessary for a certain computation (Clojure maps are immutable, but dissoc'ing away a critical piece of data leads to the same problem)."

One feature of clojure that's worth pointing out is the idea of a validator on a reference type. The reference types are boxes that can only be changed in thread-safe ways. For example, a ref is a container that can only be modified inside of a transaction. You could write:

    (def obj (ref {:foo 3 :bar :5} :validator validate-my-model)
That creates a ref that hold a map with two keys, foo and bar. It also will call the function "validate-my-model" whenever you try to modify the map. validate-my-model is a function that takes the new-state as an argument, and throws an exception or returns false if the new state is not acceptable. Let's say the definition of validate-my-model looks like:

    (defn validate-my-model [new-state]
        (assert (map? new-state))
        (assert (int? (new-state :bar)))
        (assert (int? (new-state :foo)))
        (assert (not (= 0 (new-state :bar))
        (assert (> (new-state :bar) (new-state :foo))
        true)

 Now if you want to modify/update that object (for example, to remove the key :foo from the object), you would do
    (dosync 
        (alter obj #(dissoc % :foo)))
Before that change is committed, the validator function is run. In this case, your change would throw an exception because the of line (int? (new-state :foo))

(new-state :foo) returns nil, and (assert (int? nil) will throw an exception.

Vars, refs and agents now support this (and maybe atoms but I'm not sure). I've found the technique extremely powerful. I use it all over my code. What's also nice is that it serves as a form of testing. I know that all of my models have the correct types and relationships, because it's not possible to change the objects without calling the validator.



That's very cool; thanks for sharing.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: