Thanks for both answers! I figured out a slightly different way of doing it by putting the let assignments into a string with a "nothing" expression, parsing the string, and then inserting the actual expression to be evaluated into the correct place in the let block:
function run(assignments,program) program_string="let" for pair in assignments program_string="$(program_string) $(pair[1])=$(pair[2]);" end program_string="$(program_string) nothing; end" program_final=parse(program_string) program_final.args[1].args[end]=program eval(program_final) end I can now evaluate the same expression with different inputs in parallel without worrying that they might conflict because all the variables are local, e.g.: pmap(dict->run(dict,:(x+y*y)), [{:x=>2,:y=>5},{:x=>6,:y=>10}]) *2-element Array{Any,1}:* * 27* * 106* Thanks for your help! Mike On Thursday, December 11, 2014 10:34:22 PM UTC+13, Mike Innes wrote: > > You can do this just fine, but you have to be explicit about what > variables you want to pass in, e.g. > > let x=2 > exp=:(x+1) > eval(:(let x = $x; $exp; end)) > end > > If you want to call the expression with multiple inputs, wrap it in a > function: > > let x=2 > exp=:(x+1) > f = eval(:(x -> $exp)) > f(x) > end > > > On 11 December 2014 at 06:32, Jameson Nash <vtj...@gmail.com <javascript:> > > wrote: > >> I'm not quite sure what a genetic program of that sort would look like. I >> would be interested to hear if you get something out of it. >> >> Another alternative is to use a module as the environment: >> >> module MyEnv >> end >> eval(MyEnv, :(code block)) >> >> This is (roughly) how the REPL is implemented to work. >> >> On Thu Dec 11 2014 at 1:26:57 AM Michael Mayo <mm...@waikato.ac.nz >> <javascript:>> wrote: >> >>> Thanks, but its not quite what I'm looking for. I want to be able to >>> edit the Expr tree and then evaluate different expressions using variables >>> defined in the local scope,not the global scope (e.g. for genetic >>> programming, where random changes to an expression are repeatedly evaluated >>> to find the best one). Using anonymous functions could work but modifying >>> the .code property of an anonymous function looks much more complex than >>> modifying the Expr types. >>> >>> Anyway thanks for your answer, maybe your suggestion is the only >>> possible way to achieve this! >>> >>> Mike >>> >>> >>> On Thursday, December 11, 2014 6:56:15 PM UTC+13, Jameson wrote: >>> >>>> eval, by design, doesn't work that way. there are just too many better >>>> alternatives. typically, an anonymous function / lambda is the best and >>>> most direct replacement: >>>> >>>> let x=2 >>>> println(x) # Line 1 >>>> exp = () -> x+1 >>>> println(exp()) # Line 2 >>>> end >>>> >>>> >>>> On Wed Dec 10 2014 at 10:43:00 PM Michael Mayo <mm...@waikato.ac.nz> >>>> wrote: >>>> >>>>> Hi folks, >>>>> >>>>> I have the following code fragment: >>>>> >>>>> x=1 >>>>> let x=2 >>>>> println(x) # Line 1 >>>>> exp=:(x+1) >>>>> println(eval(exp)) # Line 2 >>>>> end >>>>> >>>>> It contains two variables both named x, one inside the scope defined >>>>> by let, and one at global scope. >>>>> >>>>> If I run this code the output is: >>>>> 2 >>>>> 2 >>>>> >>>>> This indicates that (i) that line 1 is using the local version of x, >>>>> and (ii) that line 2 is using the global version of x. >>>>> >>>>> If I remove this global x I now get an error because eval() is looking >>>>> for the global x which no longer exists: >>>>> >>>>> let x=2 >>>>> println(x) # Line 1 >>>>> exp=:(x+1) >>>>> println(eval(exp)) # Line 2 >>>>> end >>>>> >>>>> 2 >>>>> >>>>> ERROR: x not defined >>>>> >>>>> >>>>> My question: when evaluating an expression using eval() such as line >>>>> 2, how can I force Julia to use the local (not global) version of x and >>>>> thus avoid this error? >>>>> >>>>> >>>>> Thanks >>>>> >>>>> Mike >>>>> >>>> >