You could do it like so:
A macro which defines a type-specific version @self_MyType of your @self
macro at the definition of the type:
@with_self type MyType
x
end
Then use that generated macro when defining the function:
@self_MyType function inc()
x += 1
end
This avoids any at little extra cost. The only down side is that you
cannot easily handle SomeoneElsesType. I do something similar in
https://github.com/mauro3/Parameters.jl/blob/cb147097de1cad1dd5c089243743f21a576a4a32/src/Parameters.jl#L381
where I construct a type specific macro: @unpack_MyType.
(And on a side note, and I think repeating myself from an earlier
thread, why don't you use Parameters.jl's @unpack instead? Consider
this:
type MyType
delta
end
# somewhere else, maybe far away, define:
@self MyType function f(x)
sin(pi*x + delta)
end
# ...
# some time far in the future add a field to MyType:
type MyType
delta
pi
end
# and now your function f breaks silently!
Being explicit with what you unpack from MyType, using e.g. @unpack, avoids this.
)
On Fri, 2016-09-30 at 00:53, Marius Millea <
marius...@gmail.com> wrote:
> 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>
>>