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/ >