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 <[email protected]> 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>
>>

Reply via email to