Let me take a stab at you parametrization question > * Parametrization of "function groups" * > > Lets say I have a bunch of functions that provide database operations > (read, write, delete, ...). They all share information about the > database the operate on. In an OO language, I would define these > methods in the same class and an instance variable would define the > database. The advantage is, that the caller side does not need to be > aware of the database name. I can create an instance somewhere and > pass around the object. I can also create several objects with > different database configurations. > > Currently I can think of 2 approaches to implement this in clojure: > > a) Each function also defines a database parameter > The downside is that the caller needs to fill in the value every time. > > b) The function invocation needs be part of something else, e.g. (do- > with-db "mydbname" (db-write) (db-read) ... ). > Here, the caller still needs to be aware of this setting. > > What is the clojure way of dealing with this? Do I overvalue this > problem because of my OO background? I am not asking for OO features > like inheritance. My goal is simply to avoid repetition and > scattering.
My current solution to this is to use the macro system, closures (I can never spell this right now...) and namespaces to solve this problem. Again, let's use your database question as an example. Assume we have a db with three tables *articles *comments *users We want to be able to perform CRUD on these tables. Let's start by designing a crud-utils namespace (ns crud-utils (:use clojure.contrib.with-ns)) (defn *create* [con table & params] ...) (defn *read* [con table & params] ...) (defn *update* [con table & params] ...) (defn *destroy* [con table & params] ...) Okay, assume each of those function wrap SQL as you see fit. Now, we'll add a macro to help wrap the tables. (This macro isn't complete. It's only an outline) (defmacro defmodel [con table a-ns] (let [fn-params (gensym "params_")] `(with-ns (quote ~ns) (do (def create (fn [& ~fn-params] (apply *create* ~con ~table ~fn- params))) (def read (fn [& ~fn-params] (apply *read* ~con ~table ~fn- params))) (def update (fn [& ~fn-params] (apply *update* ~con ~table ~fn- params))) (def destroy (fn [& ~fn-params] (apply *destroy* ~con ~table ~fn- params))) )))) This macro gives us a way of currying the CRUD functions, and storing them in a namespace. Simply call the macro to create crud for each table (defmodel db-con "articles" model.articles) (defmodel db-con "comments" model.comments) (defmodel db-con "users" model.users) Now, for the last part. Switch to another ns (ns my-app (require [models [articles :as articles] [comments :as comments] [users :as users]])) (articles/create ...) ;This now inserts a record into the articles table. I have a more full fledged example working here: http://github.com/francoisdevlin/devlinsf-clojure-utils/tree/master Check out the namespace lib.devlinsf.model-utils It's still a work in progress, in desperate need of cleanup. Still, the defmodel macro works as described. Happy Hacking Sean --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---