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

Reply via email to