Open xitology opened 8 years ago
If you're making a macro dsl, you should probably use an infix operator.
@tkelman From my perspective, .
is an infix operator since (a+b).(c+d)
is well-formed Julia syntax.
This was discussed extensively in #11891 and #7232.
Since julia doesn't require semicolons at the ends of statements, the pattern
(obj.meth1(...)
.meth2(...)
.meth3(...))
doesn't work well because after obj.meth1(...)
we don't know to expect any further expressions.
However putting the dot at the end of the line solves this. The following parses fine:
@query(
table.
filter(predicate).
group(attribute).
select(...))
@xitology but an infix operator that doesn't allow spaces ;) Is there any reason not to use |>
instead? feels like it would read better. I like that dot is forced to be written tightly. We have so many uses of . now with the broadcast notation, I think it is important to keep the use of it constrained so that code is written in a more consistent manner.
My (ab)use of Julia syntax is certainly unorthodox and I'm sure will be frowned upon by Julia developers. The .
is used as a monadic composition operation (like >=>
), while for |>
I use :
. You can see real examples here and here. As you can see, .
is being used to mimic attribute access and using any other operator in place of .
will make the syntax much more heavyweight.
That said, I don't want to make it a discussion of my stylistic choices in DSL design. This is hardly a great argument for changing language parser. I just used it as one example where one might prefer method-chaining.
As opposed to f<space>(
, which is, arguably, poor style, and shouldn't appear in real code, it's not unreasonable to see a<space>.b
in code like this:
somefunc(
big_expr
.attr)
Indeed, you could write
somefunc(
big_expr.
attr)
but I think the former is more stylistically appropriate and would be the first choice for most programmers. I understand that you cannot use it without wrapping in parentheses, but that's also the case in Python.
I don't know if it interferes with other language features (like @macro<space>()
), but if not, I just don't see why it must be prohibited.
I'm sorry for spamming this issue, but here's another argument. Even though currently method-chaining APIs for Julia do not exist, it looks like you are going to enable overriding the attribute access operator (see #1974). If so, I'm sure method-chaining APIs will appear even without macros, so this issue will probably be raised again.
There doesn't seem to be anything actionable here.
@JeffBezanson Is it that it would be inconvenient in the parser to support this, or that it's just plain impossible to support? This is a particularly important case for us for code ergonomics reasons.
It's certainly possible; indeed we allowed it prior to v0.4. We decided to remove it in #11891, but it seems to me the argument there wasn't overwhelming, and indeed a couple people said we might want to revisit this if we added dot overloading, which we did.
Could you give an example of the specific syntax you'd like to use? One thing we probably cannot support is
obj.method1(x)
.method2(y)
.method3(y)
However it already works if you put the dots at the end of lines:
obj.method1(x).
method2(y).
method3(y)
Some people seem to consider that completely unacceptable, but that seems overly fussy to me.
Would it be possible to at least allow parsing the former syntax inside of parens? In either case, it would be a nonbreaking change.
If we removed the rule about spaces before dots, yes, I think that would just work. People will surely then try it in statement position though.
First, thank you for looking again at this ticket. As Kyrylo noted above, our primary use case is "abusing" the @macro syntax parser in order to construct a familiar "fluent interface". As such, I don't think using leading periods "in statement position" would be particularly common. Currently, we have single line queries, such as below.
@query(department.filter(count(employee)>2).count())
As the queries get much longer and involved, we'd like a way to make them multi-line. Of course, we could ask users to use the period at the end of each line, as Jeff noted. I don't think it is particularly nice to read or customary. Further, as you append new operators to the end, you have to modify the previous line for the trailing period, and hence it shows up as 2 lines changed in source code control rather than a single insertion. Here's how we'd prefer to line-break the previous query for readability.
# doesn't work
@query(
department
.filter(count(employee)>2)
.count()
)
One potential alternative is the begin/end variant. However, I can't collapse it all into a single line without adding periods; this is an odd rule to explain to casual users. That said, adding another query in the chain doesn't involve modifying previous lines. So, this is probably the alternative we'd promote if leading-periods is not permitted.
@query begin
department
filter(count(employee)>2)
count()
end
We have tried to use |>
at the beginning of each line, and that works, however, |>
is a visually large indicator and gets to be quite ugly in single-line forms with involved compositions. The period (.
) is really the best "non-distracting" indicator for expression composition. Of course, long term, we may need to implement our own parser. That said, our desire to create a "fluent" interface for a complex library will not be uncommon.
Ok, we can make the parenthesized @query( )
case work just by removing the error. Beyond that, the "fluent" syntax comes from languages that require semicolon statement delimiters, so we're probably stuck there.
Kyrylo also mentioned it's usefulness in regular function calls.
somefunc(
big_expr
.attr)
Is this the same production? Also, I think Kyrylo noted that having parenthesis required is the case for Python as well.
Yes.
Julia 0.4 deprecated and Julia 0.5-dev made an error the
a<space>.b
syntax:It prevents me from using a "method-chaining" pattern, which is common in some languages and frameworks:
Admittedly, it is less common in Julia as it lacks special method syntax, but I happen to use it in my experimental Julia-based query DSL:
It is possible to un-deprecate this syntax? I found the original commit 28e7bd45, but it has no justification for deprecating it in the first place.