My apologies, a let block *is* required otherwise the variables are being 
defined at global scope. The corrected function:

function run(assignments,program)
  block=Expr(:block)
  args=Expr[]
  for pair in assignments
    append!(args, [Expr(:(=), pair[1], pair[2])])
  end
  append!(args,[program])
  block.args=args
  program_final=Expr(:let, block)
  eval(program_final)
end

Mike

On Friday, December 12, 2014 11:43:54 AM UTC+13, Michael Mayo wrote:
>
> Yes you are right! The final version with the strings removed:
>
> function run(assignments,program)
>   program_final=Expr(:block)
>   args=Expr[]
>   for pair in assignments
>     append!(args, [Expr(:(=), pair[1], pair[2])])
>   end
>   append!(args,[program])
>   program_final.args=args
>   eval(program_final)
> end
>
> Turns out that making a let expression is not required; a simple block 
> expression does the job.
> Mike
>
> On Friday, December 12, 2014 11:07:42 AM UTC+13, Mike Innes wrote:
>>
>> Great that you got this working, but I strongly recommend working with 
>> expression objects here as opposed to strings. It's likely to be more 
>> robust and will mean you can use data that isn't parseable (i.e. most 
>> things other than numbers) as inputs.
>>
>> On 11 December 2014 at 21:40, Michael Mayo <mm...@waikato.ac.nz> wrote:
>>
>>> 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> 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> 
>>>>> 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
>>>>>>>>
>>>>>>>  
>>>>
>>

Reply via email to