Pretty weird. I can replicate your error but can't explain it. I guess there's 
an interaction between eval and the way that the reader knows about namespaces, 
with the creation of a new namespace during a call to eval not making it 
available later in the same call... I'm not at all clear about how namespaces 
are managed so I don't know for sure.

However, if you can separate the require from the rest of the user's string 
then you can work around this.

First of all, if you know ahead of time what libs will be required then you can 
just require them in the normal way, without evaling strings, etc. 

But if for some reason the lib name has to be coming in as a string at runtime 
then you can do something like this:

(def expr1 "(require '[foo :as f])")

(def expr2 "(f/bar a)")

(do (eval (read-string expr1))
    ((eval (list 'fn '[a] (read-string expr2))) 3))

Here my foo library is just:

(ns foo)

(defn bar [x] (+ x x))

And running the "do" call above raises no exception and returns 6.

 -Lee



On Aug 1, 2012, at 5:32 PM, Andrew Cheng wrote:

> Thanks Evan and Lee....  Lee's approach works in my code except for one 
> interesting wrinkle. The item that I pass in ('a' in the example) can only 
> really be used if a particular library is loaded.
> 
> So what I'm doing now is taking the code string from the user -- user-string 
> -- and wrapping it like this 
> 
> (format "(do (require '[my.lib :as lib]) (try %s (catch Exception e e)))" 
> user-string)
> 
> ... bound to expr. And then I get the result...
> 
> (try ((eval (list 'fn '[a] (read-string expr))) a) (catch Exception e e))
> 
> ... This is all presented to the user in a Seesaw UI form. 
> 
> Here's the wrinkle: code that uses any fn from lib throws an exception No 
> such namespace: lib
> 
> But if I try again with just a (the value) or any other expression like 1, 
> that succeeds. And then if I try the code from the initial attempt (the exact 
> code that failed in the previous paragraph) it now also succeeds! Why might 
> that be?
> 
> 
> On Tue, Jul 31, 2012 at 8:30 PM, Lee Spector <> wrote:
> 
> An approach that doesn't involve dynamic variables is to build, evaluate, and 
> then call a function that's made out of the given code and takes an argument 
> for the variable.
> 
> Assuming for the moment that the code is in symbolic form (rather than string 
> form) like this:
> 
> => (def exp 'a)
> #<Var@2dd1082f: a>
> 
> Then you can do something like:
> 
> => (let [a 0] ((eval (list 'fn '[a] exp)) a))
> 0
> 
> It's easier to see why this is useful with a slightly more complex piece of 
> code (but it could be anything):
> 
> => (def exp '(+ a 100))
> #<Var@2dd1082f: (+ a 100)>
> 
> => (let [a 0] ((eval (list 'fn '[a] exp)) a))
> 100
> 
> If your code really is in a string then you want to call read-string on it:
> 
> => (def strexp "(+ a 100)")
> #<Var@45d1c3cd: "(+ a 100)">
> 
> => (let [a 0] ((eval (list 'fn '[a] (read-string strexp))) a))
> 100
> 
> Of course the outermost "a"s here could and probably should be something 
> else, since that'd be less confusing (I just used "a" to better match the 
> original question):
> 
> => (let [foo 0] ((eval (list 'fn '[a] (read-string strexp))) foo))
> 100
> 
>  -Lee
> 
> 
> On Jul 31, 2012, at 7:32 PM, Evan Mezeske wrote:
> 
> > This thread on SO might be helpful: 
> > http://stackoverflow.com/questions/6221716/variable-scope-eval-in-clojure .
> >
> > On Tuesday, July 31, 2012 2:02:30 PM UTC-7, Andrew wrote:
> > I have a value and a string. The string contains valid Clojure code and it 
> > mentions a variable. I'd like to let-bind that variable to the value and 
> > then evaluate the string. Can this be done?
> >
> > As a small example, I thought this would work: (let [a 0] (eval 'a)))
> >
> > Or maybe this:
> > user> (let [a 0] (eval 'user/a))
> >
> > My initial attempt was this: (let [a 0] (eval (read-string "a")))
> >
> > These all result in an exception...
> 
> --
> 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
> 
> 
> -- 
> 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

--
Lee Spector, Professor of Computer Science
Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspec...@hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438

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