Josh.F
Josh.F

Reputation: 3806

Dynamically add variables to let statement in clojure

(I saw this question, but it's a different problem)

I want to be able to dynamically create variables within a let statement, for example from a list. So to get the following:

(let [a (my-fn :a)
      b (my-fn :b)
      c (my-fn :c)])

could I do something like this? (especially, without macros?)

(let [ (map (fn [x] '(x (my-fn x)))
            [:a :b :c])]) ;;<- this code obviously doesn't work

EDIT: I was trying to be general about the problem, but maybe too much so. At the suggestion that this is an XY problem, that I might be solving my real problem with a bad solution, here's what I want it for: to make forms in re-frame that might have many inputs, and to reduce the complexity of writing the same thing over and over. Ex:

(let [project-form (re-frame/subscribe [:project-form])
      id           (rand-int 10000)
      project-name (reaction (:project-name @project-form))
      social-acct  (reaction (:social-acct @project-form))
      contact      (reaction (:contact @project-form))
      description  (reaction (:description @project-form))] ...)

Upvotes: 0

Views: 119

Answers (1)

Alan Thompson
Alan Thompson

Reputation: 29984

I think this is the closest you can get without using a macro:

(ns clj.core
  (:require [clojure.string :as str] )
  (:use tupelo.core))

(def data   { :a 1
              :b 2
              :c 3 } )

(let [ks      [:a :b :c]
      v2      (reduce (fn [result curr-key]
                        (update result curr-key inc))
                      data
                      ks)
      _ (spyx v2)
      {:keys [:a :b :c]}    v2
    ; {:keys ks}            v2   <- this one won't work
]
  (spyx [a b c])
)

(defn -main [] )

;=> v2 => {:a 2, :b 3, :c 4}
;=> [a b c] => [2 3 4]

We can avoid part of the trouble by just doing the operations on the original map, before you try to transform the data to separate symbols. Since destructuring using :keys is "set up" at compile time, it can't use the vector ks which (in general) could change at runtime. To get rid of the last bit of repetition of having [:a :b :c] listed twice, I think you'd have to use a macro.

Upvotes: 1

Related Questions