Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 824271
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T03:04:36+00:00 2026-05-15T03:04:36+00:00

I’m looking for an idiomatic way to get dynamically scoped variables in Clojure (or

  • 0

I’m looking for an idiomatic way to get dynamically scoped variables in Clojure (or a similar effect) for use in templates and such.

Here is an example problem using a lookup table to translate tag attributes from some non-HTML format to HTML, where the table needs access to a set of variables supplied from elsewhere:

(def *attr-table* 
  ; Key: [attr-key tag-name] or [boolean-function]
  ; Value: [attr-key attr-value] (empty array to ignore)
  ; Context: Variables "tagname", "akey", "aval"
  '(
        ; translate :LINK attribute in <a> to :href
     [:LINK "a"]    [:href aval]
        ; translate :LINK attribute in <img> to :src
     [:LINK "img"]  [:src aval]
        ; throw exception if :LINK attribute in any other tag
     [:LINK]        (throw (RuntimeException. (str "No match for " tagname)))
     ; ... more rules
        ; ignore string keys, used for internal bookkeeping
     [(string? akey)] []  )) ; ignore

I want to be able to evaluate the rules (left hand side) as well as the result (right hand side), and need some way to put the variables in scope at the location where the table is evaluated.

I also want to keep the lookup and evaluation logic independent of any particular table or set of variables.

I suppose there are similar issues involved in templates (for example for dynamic HTML), where you don’t want to rewrite the template processing logic every time someone puts a new variable in a template.

Here is one approach using global variables and bindings. I have included some logic for the table lookup:

;; Generic code, works with any table on the same format.
(defn rule-match? [rule-val test-val]
  "true if a single rule matches a single argument value"
  (cond
    (not (coll? rule-val)) (= rule-val test-val) ; plain value
    (list? rule-val) (eval rule-val) ; function call
    :else false ))

(defn rule-lookup [test-val rule-table]
  "looks up rule match for test-val. Returns result or nil."
  (loop [rules (partition 2 rule-table)]
    (when-not (empty? rules)
      (let [[select result] (first rules)]
        (if (every? #(boolean %) (map rule-match? select test-val))
          (eval result) ; evaluate and return result
          (recur (rest rules)) )))))

;; Code specific to *attr-table*
(def tagname) ; need these globals for the binding in html-attr 
(def akey) 
(def aval) 

(defn html-attr [tagname h-attr]
  "converts to html attributes"
  (apply hash-map
    (flatten 
      (map (fn [[k v :as kv]]
             (binding [tagname tagname akey k aval v]
               (or (rule-lookup [k tagname] *attr-table*) kv)))
        h-attr ))))

;; Testing
(defn test-attr []
  "test conversion"
  (prn "a" (html-attr "a" {:LINK "www.google.com"
                           "internal" 42
                           :title "A link" }))
  (prn "img" (html-attr "img" {:LINK "logo.png" })))

user=> (test-attr)
"a" {:href "www.google.com", :title "A link"}
"img" {:src "logo.png"}

This is nice in that the lookup logic is independent of the table, so it can be reused with other tables and different variables. (Plus of course that the general table approach is about a quarter of the size of the code I had when I did the translations “by hand” in a giant cond.)

It is not so nice in that I need to declare every variable as a global for the binding to work.

Here is another approach using a “semi-macro”, a function with a syntax-quoted return value, that doesn’t need globals:

(defn attr-table [tagname akey aval]
  `(
     [:LINK "a"]   [:href ~aval]
     [:LINK "img"] [:src ~aval]
     [:LINK]       (throw (RuntimeException. (str "No match for " ~tagname)))
     ; ... more rules     
     [(string? ~akey)]        [] )))

Only a couple of changes are needed to the rest of the code:

In rule-match? The syntax-quoted function call is no longer a list:
- (list? rule-val) (eval rule-val) 
+ (seq? rule-val) (eval rule-val) 

In html-attr:
- (binding [tagname tagname akey k aval v]
- (or (rule-lookup [k tagname] *attr-table*) kv)))
+ (or (rule-lookup [k tagname] (attr-table tagname k v)) kv)))

And we get the same result without globals. (And without dynamic scoping.)

Are there other alternatives to pass along sets of variable bindings declared elsewhere, without the globals required by Clojure’s binding?

Is there an idiomatic way of doing this, like Ruby’s binding
or Javascript’s function.apply(context)?

Update

I was probably making it too complicated, here is what I assume is a more functional implementation of the above – no globals, no evals and no dynamic scoping:

(defn attr-table [akey aval]
  (list
    [:LINK "a"]   [:href aval]
    [:LINK "img"] [:src aval]
    [:LINK]       [:error "No match"]
    [(string? akey)] [] ))

(defn match [rule test-key]
  ; returns rule if test-key matches rule key, nil otherwise.
  (when (every? #(boolean %)
          (map #(or (true? %1) (= %1 %2))
            (first rule) test-key))
    rule))

(defn lookup [key table]
  (let [[hkey hval] (some #(match % key)
                      (partition 2 table)) ]
    (if (= (first hval) :error)
      (let [msg (str (last hval) " at " (pr-str hkey) " for " (pr-str key))]
        (throw (RuntimeException. msg)))
      hval )))

(defn html-attr [tagname h-attr]
  (apply hash-map
    (flatten
      (map (fn [[k v :as kv]]
             (or
               (lookup [k tagname] (attr-table k v))
               kv ))
        h-attr ))))

This version is shorter, simpler and reads better. So I suppose I have no need for dynamic scoping, at least not yet.

Postscript

The “evaluate everyting every time” approach in my update above turned out to be problematic , and I couldn’t figure out how to implement all the conditional tests as a multimethod dispatch (although I think it should be possible).

So I ended up with a macro that expands the table to a function and a cond. This retains the flexibility of the original eval implementation, but is more efficient, takes less coding and doesn’t need dynamic scoping:

(deftable html-attr [[akey tagname] aval]
   [:LINK ["a" "link"]] [:href aval]
   [:LINK "img"]        [:src aval]
   [:LINK]              [:ERROR "No match"]
   (string? akey)        [] ))))

expands into

(defn html-attr [[akey tagname] aval]
  (cond
    (and 
      (= :LINK akey) 
      (in? ["a" "link"] tagname)) [:href aval]
    (and 
      (= :LINK akey) 
      (= "img" tagname))          [:src aval]
    (= :LINK akey) (let [msg__3235__auto__ (str "No match for "
                                             (pr-str [akey tagname])
                                             " at [:LINK]")]
                     (throw (RuntimeException. msg__3235__auto__)))
    (string? akey) []))

I don’t know whether this is particularly functional, but it is certainly DSLish (make a microlanguage to simplify repetitive tasks) and Lispy (code as data, data as code), both of which are orthogonal to being functional.

On the original question – how to do dynamic scoping in Clojure – I suppose the answer becomes that the idiomatic Clojure way is to find a reformulation that doesn’t need it.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T03:04:37+00:00Added an answer on May 15, 2026 at 3:04 am

    Your approach to the problem doesn’t seem to be very functional, and you are using eval too often; this smells like bad design.

    Instead of using snippets of code that you pass to eval, why not use proper functions instead? If the variables required are fixed for all of the patterns, you can pass them in directly as arguments; if they are not, you can pass in the bindings as a map.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.