Stream: helpdesk (published)

Topic: ✔ Interpolating operator in quoted expression


view this post on Zulip mbaz (May 03 2022 at 18:15):

This works:

julia> :( x + y )
:(x + y)

I'd like to interpolate an operator instead of having a hard-coded +. I can do this:

julia> op = :+
:+
julia> :( $op(x, y) )
:(x + y)

Is there a way to keep the x op y syntax? This fails:

:( x $op y )
ERROR: syntax: missing comma or ) in argument list

view this post on Zulip Gunnar Farnebäck (May 03 2022 at 18:47):

I doubt it. If it's not syntactically okay it's hard to get further. Of course you can do string interpolation and Meta.parse but you probably don't want that.

view this post on Zulip mbaz (May 03 2022 at 18:50):

Thanks! Yes, I thought of Meta.parse, but basically I was just wondering if I was missing something. The manual doesn't provide clarity about this.

view this post on Zulip mbaz (May 03 2022 at 18:53):

I'm not sure why it fails, though. My mental model (which is likely wrong) is that :( x $op y ) is first converted to :( x + y ); that is, interpolation happens before further parsing of the quote. Probably parsing occurs before interpolation.

view this post on Zulip Gunnar Farnebäck (May 03 2022 at 20:33):

It would be kinda hard to interpolate before parsing. E.g. making sense of

julia> op = [:+, :-]
2-element Vector{Symbol}:
 :+
 :-

julia> :($(op[2])(x, y))
:(x - y)

view this post on Zulip mbaz (May 03 2022 at 21:09):

Couldn't it do :( $(op[2])(x, y) ) -> :( -(x, y) ) -> :( x - y )? Interpolate first, then parse.

view this post on Zulip Sukera (May 03 2022 at 21:10):

the latter two are the same though, from the parsers' POV

view this post on Zulip Sukera (May 03 2022 at 21:12):

the trouble is that :( x $y z) could, depending on y, be :( -(x,z) ) or :( x g z ), which would be a syntax error

view this post on Zulip Sukera (May 03 2022 at 21:12):

so you _have_ to parse & evaluate y before you're done parsing the outer expression, just to decide if the outer expression is valid

view this post on Zulip Gunnar Farnebäck (May 03 2022 at 21:23):

How would it know the meaning of (op[2]) before parsing?

view this post on Zulip Sukera (May 03 2022 at 21:28):

it doesn't, but as $(op[2]) is a complete expression already, it is free to parse & evaluate that in isolation

view this post on Zulip mbaz (May 03 2022 at 21:28):

I see as similar to string interpolation: just blinldy replace tokens inside the quote (that is, replace $(op[2]) with :-), then parse the resulting quote. If it is invalid, throw a syntax error, but not before.

view this post on Zulip mbaz (May 03 2022 at 21:30):

@Sukera I don't know what you mean by "in isolation". In both :( $op(x,y) ) and in :( x $op y ), $op has the same value and should be parsed and evaluated identically?

view this post on Zulip mbaz (May 03 2022 at 21:32):

Clearly it is not just a parsing problem:

julia> op = :+
:+

julia> Meta.parse("x $op y")
:(x + y)

view this post on Zulip Sukera (May 03 2022 at 21:34):

well.. that's because :() is not actually an Expr literal?

view this post on Zulip Sukera (May 03 2022 at 21:35):

so it's not quite doing the same as what you're writing with Meta.parse

view this post on Zulip Sukera (May 03 2022 at 21:35):

what parse gets is already "x + y" - there's never an expression interpolation going on

view this post on Zulip Sukera (May 03 2022 at 21:36):

:( ... ) is a QuoteNode literal, which returns whatever expression is enclosed in the brackets

view this post on Zulip mbaz (May 03 2022 at 21:36):

Right.

view this post on Zulip Sukera (May 03 2022 at 21:37):

so at that point, you run into a conundrum - do you lower first, or do you interpolate first?

view this post on Zulip Sukera (May 03 2022 at 21:37):

when parsing the inner expression, that is

view this post on Zulip Sukera (May 03 2022 at 21:38):

logically, interpolation happens after lowering, because only then will the overall structure no longer change - you take a finished & lowered expression and splice it into another lowered expression tree

view this post on Zulip Sukera (May 03 2022 at 21:38):

what you're proposing is doing that before the outer expression tree is done lowering, to change how the final tree looks

view this post on Zulip mbaz (May 03 2022 at 21:39):

Well, not proposing, just trying to understand :sweat_smile:

view this post on Zulip Sukera (May 03 2022 at 21:40):

:)

view this post on Zulip Sukera (May 03 2022 at 21:41):

suppose you allow that - I think you'd quickly get very unlucky with interpolation performance, because then you'd have to potentially rebalance/relower the expression tree after every interpolation, which could get oh so very expensive with macros

view this post on Zulip Sukera (May 03 2022 at 21:42):

in essence, they're doing the same interpolation thing, just with different surface level syntax & a slightly different step in the pipeline, I think

view this post on Zulip mbaz (May 03 2022 at 21:46):

The way I interpret what you're saying (and this is probably what Gunnar also meant) is that the parser doesn't know what to do with what is essentially :( token1 token2 token3 ), because it doesn't know (yet) that token2 is an operator (or function in general).

Whereas in :( token1 operator token3 ) and :( token2(token1, token3 ), it's clear which items are functions. Is that right?

view this post on Zulip Sukera (May 03 2022 at 21:52):

yeah, should serve well enough as a mental model

view this post on Zulip Sukera (May 03 2022 at 21:53):

except for the first one, you can take a look at the difference with Meta.@dump

view this post on Zulip Sukera (May 03 2022 at 21:54):

though in this case, you won't see one with + because they parse to the same thing since they're both valid and the first one won't parse at all, because it's not julia code

view this post on Zulip Sukera (May 03 2022 at 21:56):

either way, it depends on what token2 _is_ to work, and since only infix operator literals (or non-complex literal interpolations) are allowed there, if the parser (waaaay before lowering or the concept of a "function" is a thing) can't tell, you can't do it

view this post on Zulip Notification Bot (May 03 2022 at 21:57):

mbaz has marked this topic as resolved.


Last updated: Nov 06 2024 at 04:40 UTC