Re: [julia-users] dispatch based on expression head

2014-09-18 Thread Tony Fong
Actually, having dispatch based on expression head can really help lint 
Lint itself. One thing that keeps bugging me is that currently I can never 
be sure I have covered all possible Expr head types. For example, the other 
day @pao pointed out "bitstype 8 MyBitsType" doesn't lint. I have never 
used bitstype so I would not have known this. Having a discoverable way to 
go through all concrete subtypes of an abstract Expr would help catch lint 
gaps as the language evolves.

On Sunday, September 14, 2014 4:37:34 PM UTC+7, Stefan Karpinski wrote:
>
> Avoiding allocation during parsing could really be helpful. It would be 
> possible to make the number of subexpressions a type parameter.
>
>

Re: [julia-users] dispatch based on expression head

2014-09-14 Thread Stefan Karpinski
Avoiding allocation during parsing could really be helpful. It would be
possible to make the number of subexpressions a type parameter.

On Sun, Sep 14, 2014 at 12:52 AM, Jake Bolewski 
wrote:

> Performance would come from reducing the allocation of unnecessary Any[]
> arrays for a handful of expression nodes, which has some overhead.
>  Serialization / deserialization of the AST could potentially be faster
> under a more compact representation as we know that hitting the gc is a
> performance bottleneck when doing large amounts of (de)serialization.
>  These two factors have some impact on startup time as well.
>
> One version of a function could handle all parametric expression types, it
> would just have to do runtime lookup similar to what you would have to do
> now,
> so isa(arg, Expr) && (arg::Expr).head === :headB would then just become
> isa(arg, Expr{:headB}).
>
> I wouldn't suspect this optimization to have a large impact on
> performance, but it could make things a some % faster (you hope).
>
> On Saturday, September 13, 2014 6:06:02 PM UTC-4, Tim Holy wrote:
>>
>> I wonder whether it would really have much of a performance advantage.
>> Usually
>> expressions are nested, and so an Expr{:headA} contains among its args an
>> Expr{:headB}. But you don't know until runtime what type it is, so
>> runtime
>> lookup would have to be faster than
>> isa(arg, Expr) && (arg::Expr).head == :headB ...`
>> I don't actually know, but I would be a bit surprised if it would help
>> that
>> much.
>>
>> Before someone thinks about tackling this, it would make sense to mock it
>> up;
>> make a MyExpr{:headsym}, nest a bunch of them based on real expressions,
>> and
>> then see if you get any real benefit from having the head as a type
>> parameter.
>>
>> The other negative is it would add to compilation time---currently one
>> version
>> of a function handles all expressions, but with this change you'd have to
>> compile a version for each parametric expression type. That means yet
>> slower
>> startup of any packages that do expression-parsing, and startup speed is
>> already a pretty big problem.
>>
>> --Tim
>>
>> On Saturday, September 13, 2014 01:17:00 PM Kevin Squire wrote:
>> > While this would greatly affect Match.jl, it would be a very welcome
>> change!
>> >
>> > Cheers,
>> >Kevin
>> >
>> > On Saturday, September 13, 2014, Leah Hanson 
>> wrote:
>> > > I would expect the Expr type to be abstract, with different concrete
>> > > subtypes for each current value of head. Each value of head indicates
>> a
>> > > specific structure in args, and this can just be reflected in the
>> > > definition of the subtypes. (Then you can dispatch on Expr type, use
>> > > "subtypes(Expr)" to see all possible kinds of Expr, etc.)
>> > >
>> > > -- Leah
>> > >
>> > > On Sat, Sep 13, 2014 at 10:47 AM, Jake Bolewski > > >
>> > > > wrote:
>> > >> We've actually discussed changing our expression representation to
>> use
>> > >>
>> >  types instead of the more lisp-like symbols for distinguishing
>> >  expression
>> >  types. That would allow dispatch on expression types and be more
>> >  compact.
>> >  It would, however, break almost all macros that do any kind of
>> >  expression
>> >  inspection.
>> > >>
>> > >> Hmm, interesting.  I guess the Expr type would then be Expr{:head}
>> with
>> > >> getindex / setindex overloaded to manipulate the arguments?  This
>> would
>> > >> be
>> > >> a nice change as for many nodes you would not have to allocate an
>> args
>> > >> array which could be a performance win (i guess the serialized ast's
>> > >> would
>> > >> be more compact as well).  Can't comment on whether it would be
>> enough of
>> > >> a
>> > >> win to justify such a massively breaking change.
>> > >>
>> > >>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun 
>>
>> > >>>
>> >  wrote:
>> > > On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G.
>> Johnson
>> > >
>> > > wrote:
>> > >> On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun
>> > >>
>> > >> wrote:
>> > >>> Are there better ways to do this in general?
>> > >>
>> > >> For this kind of expression-matching code, you may find the
>> Match.jl
>> > >> package handy (https://github.com/kmsquire/Match.jl), to get
>> ML- or
>> > >> Scala-like symbolic pattern-matching.
>> > >
>> > > Thanks, that's pretty cool. For simple cases like I'm using, do
>> you
>> > > know if there are advantages (or disadvantages) to using
>> Match.jl, or
>> > > should I just view it as a nicer syntax? (Obviously, when things
>> get
>> > > more
>> > > complicated Match.jl looks very appealing).
>>
>>


Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Patrick O'Leary
On Saturday, September 13, 2014 5:52:11 PM UTC-5, Jake Bolewski wrote:
>
> One version of a function could handle all parametric expression types, it 
> would just have to do runtime lookup similar to what you would have to do 
> now,
> so isa(arg, Expr) && (arg::Expr).head === :headB would then just become 
> isa(arg, Expr{:headB}).
>

I think not enough people know about Base.Meta.isexpr(). This can already 
be written isexpr(arg, :headB)--and if the implementation of Expr changes, 
you're still covered. 


Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Tim Holy
On Saturday, September 13, 2014 03:52:11 PM Jake Bolewski wrote:
> One version of a function could handle all parametric expression types, it 
> would just have to do runtime lookup similar to what you would have to do 
> now,
> so isa(arg, Expr) && (arg::Expr).head === :headB would then just become 
> isa(arg, Expr{:headB}).

But wouldn't a function like

function find_ref_expr(ex::Expr)
if ex.head == :ref
# found it!
else
for i = 1:length(ex.args)
find_ref_expr(ex.args[i])
end
end
end

end up being specialized for each different type of expression head? I'm not 
saying that specialization would not ever be useful, but I do wonder about the 
cost of compiling 20 different variants when all you care about might be a 
single head type.

Anyway, just thought I'd raise one potential reason to perhaps contemplate 
_not_ making a breaking change. In any case,  it would probably good to try to 
get a sense for what the performance tradeoff would be before tackling such a 
project.

Best,
--Tim



Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Jake Bolewski
Performance would come from reducing the allocation of unnecessary Any[] 
arrays for a handful of expression nodes, which has some overhead. 
 Serialization / deserialization of the AST could potentially be faster 
under a more compact representation as we know that hitting the gc is a 
performance bottleneck when doing large amounts of (de)serialization. 
 These two factors have some impact on startup time as well.

One version of a function could handle all parametric expression types, it 
would just have to do runtime lookup similar to what you would have to do 
now,
so isa(arg, Expr) && (arg::Expr).head === :headB would then just become 
isa(arg, Expr{:headB}).

I wouldn't suspect this optimization to have a large impact on performance, 
but it could make things a some % faster (you hope).

On Saturday, September 13, 2014 6:06:02 PM UTC-4, Tim Holy wrote:
>
> I wonder whether it would really have much of a performance advantage. 
> Usually 
> expressions are nested, and so an Expr{:headA} contains among its args an 
> Expr{:headB}. But you don't know until runtime what type it is, so runtime 
> lookup would have to be faster than 
> isa(arg, Expr) && (arg::Expr).head == :headB ...` 
> I don't actually know, but I would be a bit surprised if it would help 
> that 
> much. 
>
> Before someone thinks about tackling this, it would make sense to mock it 
> up; 
> make a MyExpr{:headsym}, nest a bunch of them based on real expressions, 
> and 
> then see if you get any real benefit from having the head as a type 
> parameter. 
>
> The other negative is it would add to compilation time---currently one 
> version 
> of a function handles all expressions, but with this change you'd have to 
> compile a version for each parametric expression type. That means yet 
> slower 
> startup of any packages that do expression-parsing, and startup speed is 
> already a pretty big problem. 
>
> --Tim 
>
> On Saturday, September 13, 2014 01:17:00 PM Kevin Squire wrote: 
> > While this would greatly affect Match.jl, it would be a very welcome 
> change! 
> > 
> > Cheers, 
> >Kevin 
> > 
> > On Saturday, September 13, 2014, Leah Hanson  > wrote: 
> > > I would expect the Expr type to be abstract, with different concrete 
> > > subtypes for each current value of head. Each value of head indicates 
> a 
> > > specific structure in args, and this can just be reflected in the 
> > > definition of the subtypes. (Then you can dispatch on Expr type, use 
> > > "subtypes(Expr)" to see all possible kinds of Expr, etc.) 
> > > 
> > > -- Leah 
> > > 
> > > On Sat, Sep 13, 2014 at 10:47 AM, Jake Bolewski   
> > > 
> > > ');>> 
> wrote: 
> > >> We've actually discussed changing our expression representation to 
> use 
> > >> 
> >  types instead of the more lisp-like symbols for distinguishing 
> >  expression 
> >  types. That would allow dispatch on expression types and be more 
> >  compact. 
> >  It would, however, break almost all macros that do any kind of 
> >  expression 
> >  inspection. 
> > >> 
> > >> Hmm, interesting.  I guess the Expr type would then be Expr{:head} 
> with 
> > >> getindex / setindex overloaded to manipulate the arguments?  This 
> would 
> > >> be 
> > >> a nice change as for many nodes you would not have to allocate an 
> args 
> > >> array which could be a performance win (i guess the serialized ast's 
> > >> would 
> > >> be more compact as well).  Can't comment on whether it would be 
> enough of 
> > >> a 
> > >> win to justify such a massively breaking change. 
> > >> 
> > >>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun  
> > >>> 
> >  wrote: 
> > > On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G. 
> Johnson 
> > > 
> > > wrote: 
> > >> On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun 
> > >> 
> > >> wrote: 
> > >>> Are there better ways to do this in general? 
> > >> 
> > >> For this kind of expression-matching code, you may find the 
> Match.jl 
> > >> package handy (https://github.com/kmsquire/Match.jl), to get ML- 
> or 
> > >> Scala-like symbolic pattern-matching. 
> > > 
> > > Thanks, that's pretty cool. For simple cases like I'm using, do 
> you 
> > > know if there are advantages (or disadvantages) to using Match.jl, 
> or 
> > > should I just view it as a nicer syntax? (Obviously, when things 
> get 
> > > more 
> > > complicated Match.jl looks very appealing). 
>
>

Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Tim Holy
I wonder whether it would really have much of a performance advantage. Usually 
expressions are nested, and so an Expr{:headA} contains among its args an 
Expr{:headB}. But you don't know until runtime what type it is, so runtime 
lookup would have to be faster than 
isa(arg, Expr) && (arg::Expr).head == :headB ...`
I don't actually know, but I would be a bit surprised if it would help that 
much.

Before someone thinks about tackling this, it would make sense to mock it up; 
make a MyExpr{:headsym}, nest a bunch of them based on real expressions, and 
then see if you get any real benefit from having the head as a type parameter.

The other negative is it would add to compilation time---currently one version 
of a function handles all expressions, but with this change you'd have to 
compile a version for each parametric expression type. That means yet slower 
startup of any packages that do expression-parsing, and startup speed is 
already a pretty big problem.

--Tim

On Saturday, September 13, 2014 01:17:00 PM Kevin Squire wrote:
> While this would greatly affect Match.jl, it would be a very welcome change!
> 
> Cheers,
>Kevin
> 
> On Saturday, September 13, 2014, Leah Hanson  wrote:
> > I would expect the Expr type to be abstract, with different concrete
> > subtypes for each current value of head. Each value of head indicates a
> > specific structure in args, and this can just be reflected in the
> > definition of the subtypes. (Then you can dispatch on Expr type, use
> > "subtypes(Expr)" to see all possible kinds of Expr, etc.)
> > 
> > -- Leah
> > 
> > On Sat, Sep 13, 2014 at 10:47 AM, Jake Bolewski  > 
> > > wrote:
> >> We've actually discussed changing our expression representation to use
> >> 
>  types instead of the more lisp-like symbols for distinguishing
>  expression
>  types. That would allow dispatch on expression types and be more
>  compact.
>  It would, however, break almost all macros that do any kind of
>  expression
>  inspection.
> >> 
> >> Hmm, interesting.  I guess the Expr type would then be Expr{:head} with
> >> getindex / setindex overloaded to manipulate the arguments?  This would
> >> be
> >> a nice change as for many nodes you would not have to allocate an args
> >> array which could be a performance win (i guess the serialized ast's
> >> would
> >> be more compact as well).  Can't comment on whether it would be enough of
> >> a
> >> win to justify such a massively breaking change.
> >> 
> >>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun 
> >>> 
>  wrote:
> > On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G. Johnson
> > 
> > wrote:
> >> On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun
> >> 
> >> wrote:
> >>> Are there better ways to do this in general?
> >> 
> >> For this kind of expression-matching code, you may find the Match.jl
> >> package handy (https://github.com/kmsquire/Match.jl), to get ML- or
> >> Scala-like symbolic pattern-matching.
> > 
> > Thanks, that's pretty cool. For simple cases like I'm using, do you
> > know if there are advantages (or disadvantages) to using Match.jl, or
> > should I just view it as a nicer syntax? (Obviously, when things get
> > more
> > complicated Match.jl looks very appealing).



Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Stefan Karpinski
I'm not sure how that makes linting impossible.

On Sat, Sep 13, 2014 at 11:56 PM, Jameson Nash  wrote:

> It would be probably be lasting, because most Exprs would no longer want
> to have an args field with a Vector{Any}
>
>
> On Saturday, September 13, 2014, Stefan Karpinski <
> stefan.karpin...@gmail.com> wrote:
>
>> Surely not in any lasting sense? With a.b syntax overloading we could
>> actually make the transition pretty smooth.
>>
>> On Sep 13, 2014, at 4:47 PM, Tony Fong  wrote:
>>
>> That'd be bad news for Lint...
>>
>> On Saturday, September 13, 2014 3:22:04 PM UTC+7, Stefan Karpinski wrote:
>>>
>>> We've actually discussed changing our expression representation to use
>>> types instead of the more lisp-like symbols for distinguishing expression
>>> types. That would allow dispatch on expression types and be more compact.
>>> It would, however, break almost all macros that do any kind of expression
>>> inspection.
>>>
>>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun 
>>> wrote:
>>>
 On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G. Johnson
 wrote:
>
> On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun
> wrote:
>>
>> Are there better ways to do this in general?
>>
>
> For this kind of expression-matching code, you may find the Match.jl
> package handy (https://github.com/kmsquire/Match.jl), to get ML- or
> Scala-like symbolic pattern-matching.
>

 Thanks, that's pretty cool. For simple cases like I'm using, do you
 know if there are advantages (or disadvantages) to using Match.jl, or
 should I just view it as a nicer syntax? (Obviously, when things get more
 complicated Match.jl looks very appealing).

>>>
>>>


Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Jameson Nash
It would be probably be lasting, because most Exprs would no longer want to
have an args field with a Vector{Any}

On Saturday, September 13, 2014, Stefan Karpinski <
stefan.karpin...@gmail.com> wrote:

> Surely not in any lasting sense? With a.b syntax overloading we could
> actually make the transition pretty smooth.
>
> On Sep 13, 2014, at 4:47 PM, Tony Fong  > wrote:
>
> That'd be bad news for Lint...
>
> On Saturday, September 13, 2014 3:22:04 PM UTC+7, Stefan Karpinski wrote:
>>
>> We've actually discussed changing our expression representation to use
>> types instead of the more lisp-like symbols for distinguishing expression
>> types. That would allow dispatch on expression types and be more compact.
>> It would, however, break almost all macros that do any kind of expression
>> inspection.
>>
>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun 
>> wrote:
>>
>>> On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G. Johnson
>>> wrote:

 On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun wrote:
>
> Are there better ways to do this in general?
>

 For this kind of expression-matching code, you may find the Match.jl
 package handy (https://github.com/kmsquire/Match.jl), to get ML- or
 Scala-like symbolic pattern-matching.

>>>
>>> Thanks, that's pretty cool. For simple cases like I'm using, do you know
>>> if there are advantages (or disadvantages) to using Match.jl, or should I
>>> just view it as a nicer syntax? (Obviously, when things get more
>>> complicated Match.jl looks very appealing).
>>>
>>
>>


Re: [julia-users] dispatch based on expression head

2014-09-13 Thread Kevin Squire
While this would greatly affect Match.jl, it would be a very welcome change!

Cheers,
   Kevin


On Saturday, September 13, 2014, Leah Hanson  wrote:

> I would expect the Expr type to be abstract, with different concrete
> subtypes for each current value of head. Each value of head indicates a
> specific structure in args, and this can just be reflected in the
> definition of the subtypes. (Then you can dispatch on Expr type, use
> "subtypes(Expr)" to see all possible kinds of Expr, etc.)
>
> -- Leah
>
> On Sat, Sep 13, 2014 at 10:47 AM, Jake Bolewski  > wrote:
>
>> We've actually discussed changing our expression representation to use
 types instead of the more lisp-like symbols for distinguishing expression
 types. That would allow dispatch on expression types and be more compact.
 It would, however, break almost all macros that do any kind of expression
 inspection.

>>>
>> Hmm, interesting.  I guess the Expr type would then be Expr{:head} with
>> getindex / setindex overloaded to manipulate the arguments?  This would be
>> a nice change as for many nodes you would not have to allocate an args
>> array which could be a performance win (i guess the serialized ast's would
>> be more compact as well).  Can't comment on whether it would be enough of a
>> win to justify such a massively breaking change.
>>
>>
>>> On Sat, Sep 13, 2014 at 2:48 AM, Gray Calhoun 
 wrote:

> On Wednesday, September 10, 2014 11:50:44 AM UTC-5, Steven G. Johnson
> wrote:
>>
>> On Wednesday, September 10, 2014 12:20:59 PM UTC-4, Gray Calhoun
>> wrote:
>>>
>>> Are there better ways to do this in general?
>>>
>>
>> For this kind of expression-matching code, you may find the Match.jl
>> package handy (https://github.com/kmsquire/Match.jl), to get ML- or
>> Scala-like symbolic pattern-matching.
>>
>
> Thanks, that's pretty cool. For simple cases like I'm using, do you
> know if there are advantages (or disadvantages) to using Match.jl, or
> should I just view it as a nicer syntax? (Obviously, when things get more
> complicated Match.jl looks very appealing).
>


>


Re: [julia-users] dispatch based on expression head

2014-09-10 Thread Gray Calhoun
Oh, cool. I'll have to read it carefully, but that looks very helpful. 
Thanks!

On Wednesday, September 10, 2014 11:24:58 AM UTC-5, John Myles White wrote:
>
> You can make parametric types that depend on symbols. Read the code in 
> Calculus.jl for examples: 
> https://github.com/johnmyleswhite/Calculus.jl/blob/master/src/symbolic.jl
>


Re: [julia-users] dispatch based on expression head

2014-09-10 Thread John Myles White
Gray,

You can make parametric types that depend on symbols. Read the code in 
Calculus.jl for examples: 
https://github.com/johnmyleswhite/Calculus.jl/blob/master/src/symbolic.jl

 -- John

On Sep 10, 2014, at 9:20 AM, Gray Calhoun  wrote:

> Hi everyone, I'm writing code using expressions fairly heavily (mainly as a 
> learning exercise), and am using lots of constructions like:
> 
> function haskey(df::MyDataType, key::Expr)
> key.head == :call  && return(all([haskey(df, x) for x in 
> key.args[2:end]]))
> key.head == :(=)   && return(haskey(df, key.args[2]))
> key.head == :block && return(all([haskey(df, x) for x in key.args]))
> key.head == :line  && return(true)
> warn("Didn't expect to get here...")
> false
> end
> 
> Some quick questions:
> 
> 1) Is there a way of mimicking Expr subtypes that I'm not aware of that would 
> let me rewrite this as several different methods? Are there better ways to do 
> this in general?
> 
> 2) Is there a list anywhere of the different possible values for Expr.head? 
> (I don't see it in the metaprogramming section of the manual, but may have 
> missed it.)
> 
> 3) How much of Julia would it break or slow down to make Expr an abstract 
> type with the contents of "head" implemented as different subtypes? (This 
> last one is mostly just asked out of curiosity.)
> 
> Thanks!



[julia-users] dispatch based on expression head

2014-09-10 Thread Gray Calhoun
Hi everyone, I'm writing code using expressions fairly heavily (mainly as a 
learning exercise), and am using lots of constructions like:

function haskey(df::MyDataType, key::Expr)
key.head == :call  && return(all([haskey(df, x) for x in key.args[2:end
]]))
key.head == :(=)   && return(haskey(df, key.args[2]))
key.head == :block && return(all([haskey(df, x) for x in key.args]))
key.head == :line  && return(true)
warn("Didn't expect to get here...")
false
end

Some quick questions:

1) Is there a way of mimicking Expr subtypes that I'm not aware of that 
would let me rewrite this as several different methods? Are there better 
ways to do this in general?

2) Is there a list anywhere of the different possible values for Expr.head? 
(I don't see it in the metaprogramming section of the manual, but may have 
missed it.)

3) How much of Julia would it break or slow down to make Expr an abstract 
type with the contents of "head" implemented as different subtypes? (This 
last one is mostly just asked out of curiosity.)

Thanks!