Hi, Am 26.05.2009 um 14:15 schrieb Rich Hickey:
Yes - keep your functions out of your data. If you are used to engine.getMove(position) it becomes: (get-move engine position) If you want polymorphism you can make get-move a multimethod. If the 'engine' concept is only about code (e.g. has no data of its own, just specifies a protocol), you can simply use names for engines in your multimethods: (get-move :minmax-engine position) (get-move :greedy-engine position)
as Rich said: multimethods to the rescue. You could define a namespace giving the interface of an engine. Thisconsists of the method definitions and maybe some default implementations.
(ns car.engine) (defmulti start "Start the engine." type) (defmulti refuel "Refuel the tank of the engine." (fn refuel-dispatch [e _] (type e))) (defmethod refuel :default [e amount] (swap! (:tank e) + amount)) (defmulti explode "Explode the engine." type) (defmethod explode :default [e] "BOOOM!") This basically looks similar to an abstract class in Java. Now we have to provide some concrete implementation. (ns car.engine.otto (:require [car.engine :as engine])) (let [type-info {:type ::Otto}] (defn make-engine [initial-fuel] (with-meta {:tank (atom initial-fuel)} type-info))) (defmethod engine/start ::Otto [e] "VROOOOM!") And another one: (ns car.engine.diesel (:require [car.engine :as engine])) (let [type-info {:type ::Diesel}] (defn make-engine [initial-fuel] (with-meta {:tank (atom initial-fuel)} type-info))) (defmethod engine/start ::Diesel [e] "TACKTACKTACKTACK!") (defmethod engine/explode ::Diesel [e] "POOOOOOOF!") Now we use our different implementations. (ns car.sportscar (:require [car.engine :as engine] [car.engine.otto :as otto])) (defn make-sportscar [] {:engine (otto/make-engine)}) (defn do-drive [car] (engine/start (:engine car)) (accelerate car) (brake car) (engine/refuel (:engine car) 100) ...) Or the diesel one.... (ns car.truck (:require [car.engine :as engine] [car.engine.diesel :as diesel])) (defn make-truck [] {:engine (diesel/make-engine)}) .... You get the idea... Although this went a bit away from the initial chess example, it should give an idea how the original problem could be solved. A more real life example is my experimental monad library based on multimethods (http://bitbucket.org/kotarak/monad). Hope this helps. Sincerely Meikel
smime.p7s
Description: S/MIME cryptographic signature