Indeed, my use case is also writing proper tests for macros using FactCheck.
I have a more bizarre use case which involves writing a lisp using julia 
(learning purposes only), but it's more out there.

In this case, it'd be nice to verify that the expression I get matches the 
one I expect.
Is there a way process an Expression and ignore nodes (i.e, linenumbernode, 
which has absolutely nothing to do with expression equality, and represents 
internal julia metadata)? It'd be a tree traversal function, maybe, but I'm 
unable to find any documentation on how to manipulate Expression objects.
Even something like cons/first/rest would be sufficient for my case.

On Wednesday, December 9, 2015 at 1:26:14 PM UTC-8, Erik Schnetter wrote:
>
> I want to test the expression
>
> ```
> macroexpand(:@fastmath :+)
> ```
>
> where `:+` is a symbol, not a function.
>
> I wasn't able to determine the difference. I used both `info` and `dump`, 
> and my LHS (the result of the expression above) and what I constructed 
> manually looked identical, and in the REPL, the epression
>
> ```
> macroexpand(:@fastmath :+) == :(:+)
> ```
> yields `true`. In `test/fastmath.jl`, it didn't. (It works fine for five 
> other expressions that are currently being tested.)
>
> Anyway -- my point being that it can be quite useful to compare 
> expressions, even if the exact value might change over time. Since Julia's 
> macros are all about manipulating expressions, having ways to output, 
> serialize, load, compare, and treat them like any other data makes totally 
> sense.
>
> -erik
>
>
>
> On Wed, Dec 9, 2015 at 4:05 PM, Yichao Yu <yyc...@gmail.com <javascript:>> 
> wrote:
>
>> On Wed, Dec 9, 2015 at 3:57 PM, Erik Schnetter <schn...@gmail.com 
>> <javascript:>> wrote:
>> > Comparing expressions is useful if you want to write a test case for a
>> > function that transforms expressions, such as e.g. `@fastmath`. I 
>> recently
>> > added some test cases, but was unable to test the result of
>> >
>> > macroexpand(:@fastmath :+)
>> >
>> > since I don't know how to explicitly construct the expected result. I 
>> know
>> > how to do it in the REPL, but this doesn't work in test cases.
>>
>> What's the difference between REPL and test script?
>>
>> julia -f -e 'println(macroexpand(:(@fastmath +)) == 
>> :(Base.FastMath.add_fast))'
>> true
>>
>>
>> >
>> > -erik
>> >
>> >
>> > On Wed, Dec 9, 2015 at 3:46 PM, Yichao Yu <yyc...@gmail.com 
>> <javascript:>> wrote:
>> >>
>> >> On Wed, Dec 9, 2015 at 3:05 PM,  <vis...@stanford.edu <javascript:>> 
>> wrote:
>> >> > Interesting. I didn't think to use dump to check differences.
>> >> >
>> >> > Another followup question. After using dump on some simple if
>> >> > statements,
>> >> > I've noticed that all blocks induce this LineNumberNode which is 
>> messing
>> >> > up
>> >> > the equality.
>> >> > Is there a way to ignore these nodes in the equality check? They 
>> show up
>> >> > in
>> >> > any kind of block statement (function, if, etc)
>> >> >
>> >>
>> >> May I ask what do you need the equality of expressions for? It doesn't
>> >> sound like a too useful concept. There can be expressions that are
>> >> equal but have different side effects due to the variables they
>> >> capture (try constructing `Expr(:call, :push!, [1, 2], 1)` twice and
>> >> eval/compare them). There can also be expressions that are equivalant
>> >> but appears differently.
>> >>
>> >> In general, I never find `==` of expressions too useful. When
>> >> processing it, you can just ignore the line number nodes if you don't
>> >> care too much about debug info (also see base/docs/Docs.jl for some
>> >> example of stripping unwanted part from a expression). There's also
>> >> MacroTools.jl which provides a nice way to process expressions.
>> >>
>> >> > eg:
>> >> >
>> >> > dump(:(if true 1 else 0 end))
>> >> >
>> >> > Expr
>> >> >
>> >> >   head: Symbol if
>> >> >
>> >> >   args: Array(Any,(3,))
>> >> >
>> >> >     1: Bool true
>> >> >
>> >> >     2: Expr
>> >> >
>> >> >       head: Symbol block
>> >> >
>> >> >       args: Array(Any,(2,))
>> >> >
>> >> >         1: LineNumberNode
>> >> >
>> >> >           file: Symbol none
>> >> >
>> >> >           line: Int64 1
>> >> >
>> >> >         2: Int64 1
>> >> >
>> >> >       typ: Any
>> >> >
>> >> >     3: Expr
>> >> >
>> >> >       head: Symbol block
>> >> >
>> >> >       args: Array(Any,(2,))
>> >> >
>> >> >         1: LineNumberNode
>> >> >
>> >> >           file: Symbol none
>> >> >
>> >> >           line: Int64 1
>> >> >
>> >> >         2: Int64 0
>> >> >
>> >> >       typ: Any
>> >> >
>> >> >   typ: Any
>> >> >
>> >> >
>> >> > dump(Expr(:if, true, Expr(:block, 0), Expr(:block,1)))
>> >> >
>> >> > Expr
>> >> >
>> >> >   head: Symbol if
>> >> >
>> >> >   args: Array(Any,(3,))
>> >> >
>> >> >     1: Bool true
>> >> >
>> >> >     2: Expr
>> >> >
>> >> >       head: Symbol block
>> >> >
>> >> >       args: Array(Any,(1,))
>> >> >
>> >> >         1: Int64 0
>> >> >
>> >> >       typ: Any
>> >> >
>> >> >     3: Expr
>> >> >
>> >> >       head: Symbol block
>> >> >
>> >> >       args: Array(Any,(1,))
>> >> >
>> >> >         1: Int64 1
>> >> >
>> >> >       typ: Any
>> >> >
>> >> >   typ: Any
>> >> >
>> >> >
>> >> > They're the same minus LineNumberNodes, because block type 
>> expressions
>> >> > always create those things.
>> >> >
>> >> >
>> >> > On Wednesday, December 9, 2015 at 7:21:55 AM UTC-8, STAR0SS wrote:
>> >> >>
>> >> >> You can also use dump() on your expressions to see how they differ
>> >> >> exactly. The normal printing doesn't really show you much.
>> >
>> >
>> >
>> >
>> > --
>> > Erik Schnetter <schn...@gmail.com <javascript:>>
>> > http://www.perimeterinstitute.ca/personal/eschnetter/
>>
>
>
>
> -- 
> Erik Schnetter <schn...@gmail.com <javascript:>> 
> http://www.perimeterinstitute.ca/personal/eschnetter/
>

Reply via email to