-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom infix operators #16985
Comments
Echoing the julia-dev thread, I think it would be useful to quote Stefan's main comment on this proposal:
As someone who's participated in a good proportion of the history of Julia development, I think it would be better to focus energy on semantic changes rather than syntactic ones. There are lots of extremely important semantic problems left to solve before Julia reaches 1.0. Note in particular that implementing this feature isn't simply a one-off diff that only the author needs to think about: everyone will have to think about how their work interacts with this feature going forward, so the change actually increases the long-term workload of every person who works on the parser. |
I think that johnmyleswhite's comments are very apropos regarding the "long term" parser changes suggested. But the "minor changes" and "optional" groups are, as far as I can see, pretty self-contained and low-impact. That is: the parser changes needed to enable the minimal version of this proposal involve only precedence and grouping for normal binary operators, the kind of changes that are more-or-less routine in other cases. A parser developer working on something unrelated would no more need to keep track of this than they need to keep track of the meaning of all of the numerous already-existing operators. |
Personally I find this syntax quite ugly and difficult to type. But I do agree it would be good to have more general infix syntax. I think the right way to think about this is as a syntax-only issue: what you want is to use I would actually consider reclaiming |
|
As to So while I like |
"headaches for parser developers" is the lowest possible concern. |
As a parser developer, I unequivocally agree with this.
|
To be clear, the long term vision here is that there would be binary The idea that this could be implemented using two ordinary functions
That's a fair point. How about replacing |
Stealing both If people want a |
OK. I understand that ...
I think you've misunderstood. |
Ah, ok, got it. |
I think that we could bikeshed about which characters to use for years. I'd trust @StefanKarpinski (as the most senior person in this conversation so far) to make a ruling, and I'd be fine with that. Even if it's something I've argued against (such as Here's some options to see what appeals: |
Stefan is not more senior than me. |
Looks as if you just nominated yourself, then, for BDFL powers on this issue! ;) |
|
I guess my vote is to use all 4 of Each of the 4 main operators, except perhaps Obviously, it would make equal sense if you swapped all slashes, so that up arrows were for evaluation and down for currying. I'm still waiting for word from On High (and I apologize for my newbie clumsiness in guessing what that meant). But if anybody taller than this bikeshed makes a ruling, for this or any other version with at least two new symbols, I'd be happy to write a short term patch (using functions) and/or a proper one (using transformations). |
We try to avoid having a BDFL to the extent possible :) |
I just thought I'd note a few quick things. First, the other benefit (the "standalone uses") of the notation that is being proposed is that Second, the idea behind this is to keep the notation consistent. There's already a Third, the possibility of using direct infix as |
I emphatically do not agree. The proposed syntax is – forgive me – ASCII salad, verging on some of the worst offenses of Perl and APL, without precedent in other languages to give the casual reader a clue of what's happening. The current syntax, while a few characters longer (five?), is pretty clear to anyone who knows that |
I don't think this is a real problem; we can just say what the precedence of |
Yes, we already do this for the |
I didn't mean it's difficult to write the parser to make it work. I meant it leads to consistency issues, hence me saying "or it would have to treat existing infix operators differently, which could cause confusion". Among other things, consider that
Perhaps I should be clearer on what I'm saying. I'm saying that being able to describe the operation as "lpad by 10" is a lot clearer than Maybe it would help if I describe where I'm coming from. I'm a mathematician and mathematical physicist, first and foremost, and "lambda syntax", while sensible from a programming standpoint, isn't the clearest for those who are less experienced in programming. Julia is, as I understand it, primarily aimed at being a scientific computing language, hence the strong resemblance to MATLAB. I must ask - how is Compare with some of the other suggestions, such as Mind you, I looked back a bit at one of the older discussions, and I see that there HAS been a notation used in another language that would be quite nice, in theory. Haskell apparently uses |
On This is all a natural consequence of how you'd write the parser, so it's not particularly a headache in that sense. But it's not particularly intuitive for the casual user of the idiom. On the usefulness of a curry idiom On (Note: If both my suggestion of This still has similar issues in terms of operator precedence as |
Try |
@tkelman: I see the issue, but what's your point? You think we should fix the existing |
I personally think we should get rid of the existing |
I think you've missed the point. Yes, the |
I'd like to note once again that any way to define infix operators will allow creating an operator that does what Glen-O wants Personally, I think the |
I agree it's difficult to decide on the precedence for |
I'm sorry. I'm probably guiltiest of getting into back-and-forth. On the other hand, I think this thread has clearly made "useable" progress. Either of the latest suggestions Still, I think that further back-and-forth comments are probably not going to make any further progress, and I'd encourage people to use thumbs-up or thumbs-down from now on unless they have something truly new to suggest (that is, not just an orthographic change to an existing proposal). I've added "hooray" emoticons (exploding cone) to the "votable proposals". If you believe that we should not have a specialized syntax for arbitrary functions in infix position, then downvote the bug as a whole. ... ETA: I think that this discussion is now mature enough to get a |
For reference, (and I expected someone else to point it out).
Is better written
Nonstandard string literals are a seriously powerful bit of syntax. And in this case I think the result is a lot cleaner than any infix operation that can be defined. I really don't see the need to a decision tag. My feels towards this go up and down everytime I read the thread. I don't think I'll really know til I try it. And right now I don't even know what I would use it for. (Unlike some of the definitions for |
Whether or not SQL is best done with NSLs, I think there is a level of DSL that is complex enough that inline macros would be very helpful, but not so complex that it's worth writing your own microparser/tokenizer.
The inline macro proposal would enable people to, among other things, roll their own (I don't want to get into back-and-forth bikeshedding arguments, but I was responding anyway because of the below, and I do think that the inline-macro proposal kills multiple birds with one relatively-smooth stone.)
I asked earlier if it was appropriate for me to create a parser patch, and nobody answered. The only word on that so far is:
Which would seem to argue against making a patch now, as it might just sit around and bit-rot. However, now you're saying that it's not worth making a decision on this (including the decision not to decide right now?) unless we have an "implementation as a PR [or] usable prototype". What does that mean? (What is a PR?) Would a macro that used the character Right now, there are 13 participants in this bug. There are a total of 5 people who have voted on one or more of the proposals and/or downvoted the bug itself, and only one of those (me) did so after the inline macro proposal was on the table. That doesn't make me confident that it's time for prototyping yet. When the number of people who have voted since the last serious proposal is more like half the number of participants, I hope some kind of rough consensus will be becoming clear, and then it will be time for prototyping and testing and deciding (or, as the case may be, giving up on the idea). |
By "implementation as a PR [or] usable prototype". A PR is a pull request, so a patch is the term you've been using. If you made a PR it could be downloaded and tested. Like it ain't my call, but I doubt I'll be bale to make up my own opinion without something I can play with. Also +1 to not going to back and forth bike sheding. |
...or maybe an Infix.jl package with macros and nonstandard string literals. |
We have definitely reached the "working code or GTFO" point in this conversation. |
OK, here's working code then: https://github.com/jamesonquinn/JuliaParser.jl ETA: Should I reference a specific commit, or is the above link to the latest master OK? ... (That does not have any of the convenience macros I'd expect you'd want, such as the equivalents for ... I think that the current ugly hack with Note that the patch (it's not a PR yet because it targets the native bootstrapped parser, but for now the scheme one should come first in terms of PRs) is more generally useful than the issue name here. The issue name is "custom infix operators"; the patch gives infix macros, with infix operators only coming as a side effect of that. The patch as it stands is not a breaking change, but I expect that if this became the plan the next step would be to deprecate the currently-existing ... Some simple tests added. |
#11608 was closed with a pretty clear consensus that many of us do not want infix macros and the one current case of Macros are now technically generic, but their input arguments are always |
(Sorry I posted prematurely; fixed now.) In #11608, I see several negative arguments: ===
This was dealt with in the thread:
and
===
which is (partially) answered (and seconded) here by:
===
This is an interesting point. Obviously, if the macro just calls a function, then we have all the dispatch power of the function. But if it is a true macro, as with Still, this is just as much of an issue for any macro. If two packages both export a macro, you simply can't have both with "using". Is this likely to be more of a problem with infix macros? Well, it depends what people end up using them for:
Then, the function (note: the above has been edited. Initially, I thought that an R expression like ===
Which I have done. ===
This relates to the point above. Insofar as an infix macro calls a specific function, that function is still extensible through dispatch in the normal way. Insofar as it doesn't call a specific function, it is doing something structural/syntactic (such as what ===
As was pointed out in the referenced thread:
For example, which is more readable (and writeable):
or
? === Finally:
Looks pretty evenly split to me, with "who's gonna do the work" casting the deciding vote. Which is now at least partly moot; I've done the work in JuliaParser and I'd be willing to do it in Scheme if people like this idea. |
This is my last post in this thread, unless there's positive reaction to my hacked juliaparser. It is not my intention to impose my will; just to present my point of view. I'm arguing in favor of infix macros (
My response is: Julia is first of all a language for STEM programmers. Mathematicians, engineers, statisticians, physicists, biologists, machine learning people, chemists, econometricians... And one thing that I think most of those people realize is the usefulness of a good notation. To take an example I'm familiar with in statistics: adding independent random variables is equivalent to convolving PDFs, or even to convolving derivatives of CDFs, but often expressing something using the former can be an order of magnitude more concise and understandable than the latter. Infix versus prefix versus postfix is, to some degree, a matter of taste. But there are also objective reasons to prefer infix in many cases. Whereas prefix and postfix lead to indigestible precipitates of back-to-back operators like the ones that make Forth programmers sound like German politicians, or the ones that make Lisp programmers sound like a Chomskian caricature, infix puts the operators in what's often the cognitively most natural place, as near to all their operands as possible. There's a reason nobody writes math papers in Forth, and why even German mathematicians use infix operators when writing equations. Yes, infix macros could be used to write obfuscated code. But existing prefix macros are just as prone to abuse. If not abused, infix macros can lead to much clearer code.
I realize that these are just toy examples but I think the principle is valid. Could the above be done with nonstandard string literals? Well, the second and third examples would work as NSLs. But the problem with NSLs is that they give you too much freedom: unless you're familiar with the particular grammar, there's no way to be sure even what the tokens of an NSL are, let alone its order of operations. With infix macros, you have enough freedom to do all of the above examples, but not so much that it isn't clear on reading the "good" code what the tokens are and where the implied parentheses go. |
The it needs certain things to be moved from unknown unknowns to known unknowns. And unfortunately, there is not a mechanism to do this. Your arguments need a structure which does not exist. |
Now that |
I have made a package for the hack mentioned by Steven in #24404 (comment): |
I'm not how many potential infix operators this affects, but I'd really like to use
Sorry if this is already covered by this or another issue, but I couldn't find it. |
We could potentially require spaces in |
Thanks @JeffBezanson, that would be great! Would this be a special case, or a more general rule? I'm sure there are some details in what the rule should be to allow more infix operators, give clear and predictable code, and break as little as possible existing code. Anyway, I appreciate the help and the quick response. Happy new year! |
In case that |
I know this is quite an old discussion, and the question asked was asked quite some time ago, but I thought it was worth answering:
No, unfortunately, |
Frozen during 2 years, a comment and a commit 2 and 5 days ago ! See Document customizable binary operators f45b6be |
There is a discussion at https://groups.google.com/forum/#!topic/julia-dev/FmvQ3Fj0hHs about creating a syntax for custom infix operators.
...
Edited to add note: @johnmyleswhite has pointed out that the comment thread below is an invitation to bikeshedding. Please refrain from new comments unless you have something truly new to add. There are several proposals below, marked by "hooray" emoticons (exploding cone). You can use those icons to skip discussion and just read the proposals, or to find the different proposals so you can vote "thumbs up" or "thumbs down".
Up/downvotes on this bug as a whole are about whether you think that Julia should have any custom infix idiom. Up/downvotes for the specific idea below should go on @Glen-O's first comment. (The bug had 3 downvotes and 1 upvote before that was clarified.)
...
Initial proposal (historical interest only):
The proposal that seems to have won out is:
In order to have this work, there are only minor changes necessary:
<|
above that of|>
, instead of being the same.<|
group left-to-right.<|(a,b...)=(i...)->a(i...,b...)
. (as pointed out in the discussion thread, this would have standalone uses, as well as its use in the above idiom)Optional:
>|(a...,b)=(i...)->b(a...,i...)
and|<(a,b...)=a(b...)
with appropriate precedences and grouping.>>|(a...,b)=(i...)->b(i...,a...)
and<<|(a,b...)=(i...)->a(b...,i...)
with appropriate precedence and grouping.»
,⁍
, and(/or)pipe
for|>
;«
,⁌
, and(/or)rcurry
for<|
; and(/or)lcurry
for<<|
; with the single-character synonyms working as infix operators.@infix
macro in base which does the first parser fix below.Long term:
a |>op<| b
toop(a,b)
, so there's no extra overhead involved when running the code, and so that operators can actually be defined in infix position. (This is similar to how the parser currently treats the binarya:b
and the ternarya:b:c
differently. For maximum customizability, it should do this for matched synonyms, but not for unmatched synonyms, so that e.g.a |> b « c
would be still be treated as two binary operators.)(relates to #6946)
The text was updated successfully, but these errors were encountered: