Not by default, but it should be simple enough (and correct, I think) to
just call macroexpand on macro calls.

macro test(expr)
  (expr,)
end

 (@test @foo x) == (:(@foo x),)

All I meant about the let binding is that the mutating version expands to:

let a = Foo.a
  # code
  Foo.a = a
end

AFAIK let bindings have a small overhead (compared to a normal
declaration), so if a redundant assignment is a significant overhead in
your code then using the let binding will be prohibitive anyway. I haven't
particularly tested that, though, so the situation could have changed
recently.


On 13 June 2014 14:59, David Moon <dave_m...@alum.mit.edu> wrote:

> [I can't get this damned thing not to include a quote of all previous
> messages.  I guess it only works in Google Chrome; what a pain.  So sorry
> about the unnecessarily long post.]
>
> In the argument to a macro all nested macro calls are already expanded, I
> think.  It's certainly true that for complete correctness you would need to
> handle shadowing of the bindings introduced by atsign-with by local
> bindings of the same name.  It's even more true that Julia does not provide
> any assistance in processing Expr's and other AST objects, nor even much
> documentation, so far as I know.
>
> I don't understand your comment about the overhead of the let binding used
> by the mutating version of the macro.  What extra overhead is that?
>
> On Friday, June 13, 2014 3:57:07 AM UTC-4, Mike Innes wrote:
>>
>> That was my first thought, too – and it's fine in principle, but remember
>> for that macro to be correct you'd have to handle let bindings, quoting,
>> local variable declarations and expanding any macros that might result in
>> these, then test all of those things carefully to make sure it's working
>> correctly.
>>
>> Plus, if the overhead of unnecessary writes is an issue, so will be that
>> of the let binding used by the mutating version of the macro. This again is
>> probably solvable, but for all that effort you could just use the faster
>> non-mutating version and store a couple of changes by hand.
>>
>> That's not meant to put off anyone who wants to have a go at this, just
>> warning that it wouldn't be as trivial as it sounds.
>>
>> On Friday, 13 June 2014 02:01:28 UTC+1, David Moon wrote:
>>>
>>> Mike Innes' atsign with macro is good, but it would be better if it
>>> would iterate over the AST for its last argument and replace each
>>> occurrence of "field" with "obj.field".  That way there wouldn't be any
>>> unexpected assignments to fields which were not actually changed, and in
>>> general no wasted motion at run time.  The macro would be a little more
>>> complex to write but it should not be very difficult.
>>>
>>> On Thursday, June 12, 2014 6:14:15 AM UTC-4, Mike Innes wrote:
>>>>
>>>> Ok, managed to have a quick go at this – source with some examples:
>>>>
>>>> https://gist.github.com/one-more-minute/668c5c7cdd8fd8b81d35
>>>>
>>>> Currently it does nothing to avoid the issue Keno pointed out, but in
>>>> principle you could throw an error when the mutating version is used
>>>> without explicit types.
>>>>
>>>> If there's any interest in having this in Base you're welcome to it,
>>>> otherwise I'll probably just clean it up and store it in Lazy.jl.
>>>>
>>>> On Thursday, 12 June 2014 09:44:30 UTC+1, Andrew Simper wrote:
>>>>>
>>>>> Brilliant Mike! This is exactly what I was after, I just want a way to
>>>>> write shorthand names for things within a scope, and the @with macro does
>>>>> just that :) In the example I posted I split the coefficients away from 
>>>>> the
>>>>> state so that only the state needs to be returned, I think this is good 
>>>>> for
>>>>> efficiency. I'll have a play with @with and see how I go. Passing in names
>>>>> (Typename), isn't a problem, since when a new name is added there is no
>>>>> duplication in doing this.
>>>>>
>>>>> Keno, sorry for not understanding that this is probably what you meant
>>>>> when you said this would be best off done by using macros, I didn't think
>>>>> of enclosing the entire algorithm in a macro.
>>>>>
>>>>> On Thursday, June 12, 2014 4:21:58 PM UTC+8, Mike Innes wrote:
>>>>>>
>>>>>> FWIW – putting to one side the question of whether or not this is a
>>>>>> good idea – it would be possible to do this without new language syntax.
>>>>>> However, you'd have to either pass a type hint or be explicit about the
>>>>>> variables you want:
>>>>>>
>>>>>> e.g.
>>>>>>
>>>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>   @with state::SvfSinOsc, coef::SvfSinOsc
>>>>>>   # or
>>>>>>   @with state (ic1eq, ic2eq) coef (g0, g1)
>>>>>>
>>>>>>   lv1 = g0*ic1eq - g1*ic2eq
>>>>>>   lv2 = g1*ic1eq + g0*ic2eq
>>>>>>   SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>> end
>>>>>>
>>>>>> This would work in the non-mutating case by calling names() on the
>>>>>> type and making appropriate variable declarations.
>>>>>>
>>>>>> You could then go further and implement
>>>>>>
>>>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>   @with state (ic1eq, ic2eq) coef (g0, g1) begin
>>>>>>
>>>>>>     lv1 = g0*ic1eq - g1*ic2eq
>>>>>>     lv2 = g1*ic1eq + g0*ic2eq
>>>>>>     SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>>   end
>>>>>> end
>>>>>>
>>>>>> Which would walk over the expression, replacing `a` with `Foo.a`.
>>>>>> However, it would be tricky to implement this correctly since you'd have 
>>>>>> to
>>>>>> be aware of variable scoping within the expression.
>>>>>>
>>>>>> I may implement the non-mutating version of this at some point – it
>>>>>> seems like it could be useful.
>>>>>>
>>>>>>
>>>>>> On Thursday, 12 June 2014 08:21:42 UTC+1, Andrew Simper wrote:
>>>>>>>
>>>>>>> On Thursday, June 12, 2014 2:16:30 PM UTC+8, Andrew Simper wrote:
>>>>>>>>
>>>>>>>> It seems that the local keyword is a bit of a language kludge to
>>>>>>>> me, since it is implied in most cases, apart from stating the new 
>>>>>>>> scope in
>>>>>>>> the form of a for loop etc. It would seem more natural and consistent 
>>>>>>>> to me
>>>>>>>> to add the local keyword in front of all variables you want to be 
>>>>>>>> local in
>>>>>>>> scope, and everyting else is global. This line of reasoning I'm sure 
>>>>>>>> has
>>>>>>>> already been argued to death, and obviously having an implicit local 
>>>>>>>> was
>>>>>>>> decided to be best.
>>>>>>>>
>>>>>>>
>>>>>>> Having the local keyword like it is makes most sense to me, but I
>>>>>>> suppose it isn't a big deal to me that if you don't explicitly specify
>>>>>>> local you could be referring to something outside the current scope, 
>>>>>>> which
>>>>>>> is the case with for loops.
>>>>>>>
>>>>>>
>>> On Thursday, June 12, 2014 6:14:15 AM UTC-4, Mike Innes wrote:
>>>>
>>>> Ok, managed to have a quick go at this – source with some examples:
>>>>
>>>> https://gist.github.com/one-more-minute/668c5c7cdd8fd8b81d35
>>>>
>>>> Currently it does nothing to avoid the issue Keno pointed out, but in
>>>> principle you could throw an error when the mutating version is used
>>>> without explicit types.
>>>>
>>>> If there's any interest in having this in Base you're welcome to it,
>>>> otherwise I'll probably just clean it up and store it in Lazy.jl.
>>>>
>>>> On Thursday, 12 June 2014 09:44:30 UTC+1, Andrew Simper wrote:
>>>>>
>>>>> Brilliant Mike! This is exactly what I was after, I just want a way to
>>>>> write shorthand names for things within a scope, and the @with macro does
>>>>> just that :) In the example I posted I split the coefficients away from 
>>>>> the
>>>>> state so that only the state needs to be returned, I think this is good 
>>>>> for
>>>>> efficiency. I'll have a play with @with and see how I go. Passing in names
>>>>> (Typename), isn't a problem, since when a new name is added there is no
>>>>> duplication in doing this.
>>>>>
>>>>> Keno, sorry for not understanding that this is probably what you meant
>>>>> when you said this would be best off done by using macros, I didn't think
>>>>> of enclosing the entire algorithm in a macro.
>>>>>
>>>>> On Thursday, June 12, 2014 4:21:58 PM UTC+8, Mike Innes wrote:
>>>>>>
>>>>>> FWIW – putting to one side the question of whether or not this is a
>>>>>> good idea – it would be possible to do this without new language syntax.
>>>>>> However, you'd have to either pass a type hint or be explicit about the
>>>>>> variables you want:
>>>>>>
>>>>>> e.g.
>>>>>>
>>>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>   @with state::SvfSinOsc, coef::SvfSinOsc
>>>>>>   # or
>>>>>>   @with state (ic1eq, ic2eq) coef (g0, g1)
>>>>>>
>>>>>>   lv1 = g0*ic1eq - g1*ic2eq
>>>>>>   lv2 = g1*ic1eq + g0*ic2eq
>>>>>>   SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>> end
>>>>>>
>>>>>> This would work in the non-mutating case by calling names() on the
>>>>>> type and making appropriate variable declarations.
>>>>>>
>>>>>> You could then go further and implement
>>>>>>
>>>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>   @with state (ic1eq, ic2eq) coef (g0, g1) begin
>>>>>>
>>>>>>     lv1 = g0*ic1eq - g1*ic2eq
>>>>>>     lv2 = g1*ic1eq + g0*ic2eq
>>>>>>     SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>>   end
>>>>>> end
>>>>>>
>>>>>> Which would walk over the expression, replacing `a` with `Foo.a`.
>>>>>> However, it would be tricky to implement this correctly since you'd have 
>>>>>> to
>>>>>> be aware of variable scoping within the expression.
>>>>>>
>>>>>> I may implement the non-mutating version of this at some point – it
>>>>>> seems like it could be useful.
>>>>>>
>>>>>>
>>>>>> On Thursday, 12 June 2014 08:21:42 UTC+1, Andrew Simper wrote:
>>>>>>>
>>>>>>> On Thursday, June 12, 2014 2:16:30 PM UTC+8, Andrew Simper wrote:
>>>>>>>>
>>>>>>>> It seems that the local keyword is a bit of a language kludge to
>>>>>>>> me, since it is implied in most cases, apart from stating the new 
>>>>>>>> scope in
>>>>>>>> the form of a for loop etc. It would seem more natural and consistent 
>>>>>>>> to me
>>>>>>>> to add the local keyword in front of all variables you want to be 
>>>>>>>> local in
>>>>>>>> scope, and everyting else is global. This line of reasoning I'm sure 
>>>>>>>> has
>>>>>>>> already been argued to death, and obviously having an implicit local 
>>>>>>>> was
>>>>>>>> decided to be best.
>>>>>>>>
>>>>>>>
>>>>>>> Having the local keyword like it is makes most sense to me, but I
>>>>>>> suppose it isn't a big deal to me that if you don't explicitly specify
>>>>>>> local you could be referring to something outside the current scope, 
>>>>>>> which
>>>>>>> is the case with for loops.
>>>>>>>
>>>>>>

Reply via email to