On Wed, Dec 9, 2015 at 5:08 PM,  <vish...@stanford.edu> wrote:
> 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.

Expr is just a normal object and you can access the head and args fields.

>
> 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> wrote:
>>>
>>> On Wed, Dec 9, 2015 at 3:57 PM, Erik Schnetter <schn...@gmail.com> 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> wrote:
>>>
>>> >>
>>> >> On Wed, Dec 9, 2015 at 3:05 PM,  <vis...@stanford.edu> 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>
>>> > http://www.perimeterinstitute.ca/personal/eschnetter/
>>
>>
>>
>>
>> --
>> Erik Schnetter <schn...@gmail.com>
>> http://www.perimeterinstitute.ca/personal/eschnetter/

Reply via email to