I think there's at least once scenario where eval-in-a-macro is not a 
mistake, mainly when you want to generate some code that depends on 1) some 
passed in expression and 2) something which can only be known at runtime. 
Here's my example:

The macro (@self) which I'm writing takes a type name and a function 
definition, and gives the function a "self" argument of that type and 
rewrites all occurrences of the type's fields, X, to self.X. Effectively it 
takes this:

type MyType
    x
end

@self MyType function inc()
    x += 1
end

and spits out:

function inc(self::MyType)
    self.x += 1
end

(if this sounds familiar, its because I've discussed it here before, which 
spun off this <https://github.com/fcard/SelfFunctions.jl>, that I'm 
currently working on tweaking)


To do this my code needs to modify the function expression, but this 
modification depends on fieldnames(MyType), which can *only* be known at 
runtime. Hence what I'm doing is, 

macro self(typ,func)

    function modify_func(fieldnames)
        # in here I have access to `func` expression *and* 
`fieldnames(typ)` as evaluated at runtime
        # return modified func expression
    end

    quote
        $(esc(:eval))($modify_func(fieldnames($(esc(typ)))))
    end 
 
end

I don't see a cleaner way of doing this, but I'm happy to take suggestions. 

(Btw: my original question was w.r.t. that last "eval', which makes it so 
that currently this doesn't work on function closures. I'm still processing 
the several suggestions in this context...)


On Tuesday, September 27, 2016 at 5:12:44 PM UTC+2, Steven G. Johnson wrote:
>
> On Tuesday, September 27, 2016 at 10:27:59 AM UTC-4, Stefan Karpinski 
> wrote:
>>
>> But note that if you want some piece of f to be "pasted" from the user 
>> and have access to certain parts of the local state of f, it's probably a 
>> much better design to let the user pass in a function which f calls, 
>> passing the function the state that it should have access to:
>>
>
> Right; using "eval" in a function is almost always a mistake, an 
> indication that you should really be using a higher-order function. 
> <https://en.wikipedia.org/wiki/Higher-order_function>
>

Reply via email to