I'm not sure there's a way to achieve exactly what you're asking, but I'll 
note that your problem comes from Julia's scoping rules for assignment. 
I.e. if you replace

a = 1
@foo1 begin
  a += 1 # UndefVarError!
end

with 

a = 1
@foo1 begin
  2 * a 
end

then you don't get any UndefVarError. Why do you want assignment inside a 
test to apply outside the test? Not sure if this will apply to you, but I 
sometimes have code that's written this way to get around the scoping rules:

w = initial_value()
w = fixed_point(max_iter=10) do w
   w = blah(w)
   ...
   w
end


On Saturday, February 13, 2016 at 7:41:35 AM UTC-5, Robert Feldt wrote:
>
> To clarify the possible solution hinted at in my previous message here is 
> code to show how it could be done:
>
> function run_code(t::Type{Runner}, runnername::Symbol, block::Expr)
>   quote
>     for i in 1:($runnername.reps)
>       $block
>     end
>   end
> end
>
> macro foo2(runnertypename, ex)
>   rt = eval(runnertypename) # But what if Runner type not defined in 
> global scope? Risky!?
>   quote
>     local r = $(esc(runnertypename))()
>     $(run_code(rt, :r, esc(ex)))
>   end
> end
> a = 1
> @foo2 Runner begin
>   a += 1
> end
> @show(a);
>
> This works as intended and gives a lot of power for people to write their 
> own Runners but feels a bit inelegant and error prone. If there is a more 
> idiomatic way please share.
>
> /Robert 
>
> Den lördag 13 februari 2016 kl. 12:16:43 UTC+1 skrev Robert Feldt:
>>
>> When working on a possible PR for the new Base.Test infrastructure I run 
>> into a design problem of how to allow flexible control of how the expr 
>> available to a macro is executed. Sorry if this is trivial but I'd 
>> appreciate any design ideas/pointers. Simplified code below to try and 
>> explain what I mean.
>>
>> # A macro can eval in the calling context:
>> macro foo(ex)
>>   quote
>>       $(esc(ex))
>>   end
>> end
>> a = 1
>> @foo begin
>>   a += 1
>> end
>> @show(a); # a = 2
>>
>> # But lets say I want to be able to dynamically control how the expr
>> # of a macro is executed via a Runner (this is a convoluted/dummy example 
>> but 
>> # simplified from a more complex case where there are multiple types 
>> # of Runners)
>> type Runner
>>   reps::Int64
>>   Runner() = new(2)
>> end
>> run(f::Function, r::Runner) = begin
>>   for i in 1:r.reps
>>     f()
>>   end
>> end
>>
>> # Is there any way I can "package" the expr a macro has so that its 
>> execution
>> # is controlled by an instance of the Runner above while still evaluating
>> # the expr in the scope where the macro is called?
>>
>> # First try:
>> macro foo1(ex)
>>   quote
>>     r = Runner()
>>     run(r) do # UndefVarError since do-block creates new scope?
>>       $(esc(ex))
>>     end
>>   end
>> end
>> @foo1 begin
>>   a += 1 # UndefVarError!
>> end
>> @show(a);
>>
>> # What I could do is maybe have dispatch on Type{Runner}to  generate the 
>> run code to be spliced into
>> # the macro but this seems inelegant and maybe error prone since it mixes 
>> compile-time
>> # and runtime (since Type{Runner} is needed at macro expansion time).
>> # Any ideas on a clean and elegant way to accomplish this? 
>>
>> # Further details at the bottom of: 
>> https://github.com/JuliaLang/julia/pull/14971
>>
>> Thanks!
>>
>

Reply via email to