First, you could use destructuring to make your map function cleaner.
The following is exactly identical to your definition. It declares
that it will be passed one argument; because that argument is [...],
it will be a seq; it asks that the seq be split into y, the first
element, and z, a seq of the rest. This eliminates the need for first
and rest, which are really just tangential to the problem.
(map (fn [[y & z]] (x y z)) schema)

Second, as Patrick says, you want apply. It takes a function (in my
example, str), any number of "normal" arguments (here 'test'), and one
list of further arguments to supply (here args). It calls the supplied
function with the arguments specified, expanding the final list "in
place", so to speak.

user=> (def args ['hello 'world '!])
#'user/args
user=> (str 'test args)
"test[hello world !]"
user=> (apply str 'test args)
"testhelloworld!"

For your example, a definition of x that behaves more like your sql
function might be
(def x list*) ; or write it yourself: (defn x [a & b] (cons a b))

Then, to call it:
(map (fn [[y & z]] (apply x y z)) schema))
;; or (map (partial apply x) schema)

On Sep 13, 11:47 pm, Michael Ossareh <ossa...@gmail.com> wrote:
> Hi,
>
> I don't fully understand how to make real use of varargs and
> destructuring. c.c.sql/create-table is defined as follows:
>
> (create-table name & specs)
>
> Called as follows:
>
> (c.c.sql/create-table
>  :tblname
>  [:cola :text "NOT NULL" "PRIMARY KEY"]
>  [:colb :number "NOT NULL"]
>  [:colc :blob "NOT NULL")]
>
> I want to store my table definitions in a data structure (I'm open to
> which one) such that I can get access to table names later on. However
> if I store the definitions in a vector which each element is a vector
> of arguments to create-table I'm not able to pass the correct
> arguments to create-table.
>
> An example of the data structure:
>
> (def schema
>      [[:users
>        [:id :text "PRIMARY KEY" "NOT NULL"]
>        [:domain :text "NOT NULL"]
>        [:email :text :unique "NOT NULL"]
>        [:password :text "NOT NULL"]
>        [:name :text "NOT NULL"]
>        [:created :bigint "NOT NULL"]
>        [:last_login :bigint]]
>
>       [:user_token
>        [:token :text :unique "PRIMARY KEY" "NOT NULL"]
>        [:user_id :text "NOT NULL" "REFERENCES users(id) ON DELETE CASCADE"]
>        [:client :text "NOT NULL"]
>        [:created :bigint "NOT NULL"]
>        [:last_used :bigint]]])
>
> (defn x [a & b] (prn (str "a: " a)) (prn (str "b: " b)))
>
> (map (fn [y] (x (first y) (rest y))) schema)
>
> results in:
>
> ("a: :users"
> "b: (([:id :text \"PRIMARY KEY\" \"NOT NULL\"] [:domain :text \"NOT
> NULL\"] [:email :text :unique \"NOT NULL\"] [:password :text \"NOT
> NULL\"] [:name :text \"NOT NULL\"] [:created :bigint \"NOT NULL\"]
> [:last_login :bigint]))"
> "a: :user_token"
> "b: (([:token :text :unique \"PRIMARY KEY\" \"NOT NULL\"] [:user_id
> :text \"NOT NULL\" \"REFERENCES users(id) ON DELETE CASCADE\"]
> [:client :text \"NOT NULL\"] [:created :bigint \"NOT NULL\"]
> [:last_used :bigint]))")
>
> if I call create-table instead of `x` it gets two arguments, (first y)
> and a vector containing the elements in (rest y) instead of (first y)
> and each of the elements in (rest y).
>
> How is it possible for me to flatten b such that when passed to
> c.c.sql/create-table its fn arguments are satisfied? I feel like
> partial need to be used, however I haven't been able to figure it out.
>
> Any help much appreciated!
>
> Cheers,
>
> mike

-- 
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

Reply via email to