Proposal: `then`, `else` syntax to replace `&&`, `||` short-circuiting

It looks as though : is getting a bit overloaded/overused in Julia.

I rather like Swift’s a..b range syntax, as far as I can see that doesn’t conflict with anything. Also it is a more natural syntax – it would take some of the pressure off.

What think y’all? There is still time to change!

So that would be two breaking changes for some vague benefit of principle that is in the eye of the beholder, improving on something many other languages are fine with?

In any case, bikeshedding of surface syntax is always very tempting, and possibly innocuous. The proof of the pudding is in the PR: a simple grepping suggests 700+ obvious cases in Base that you would need to replace for the first syntax alone (did not count tests, etc). Making a PR would signal that you care about this enough to invest the fraction of the hours that you would expect others to devote if the change goes through. It would also allow you to assess the improvement in real-life examples.

3 Likes

Yes, I brought it up (there under my “Páll Haraldsson” name, not my nickname), still writing my counterproposal (mostly justification, performance analysis) for opening a new issue on Github.

julia> hello() = begin print("Hello"); return false end # think of this as just some slow function without side-effects and the other fast
julia> world() = begin println(" world!"); return true end

julia> hello() & world();
Hello world!

Is this the semantics we want for bitwise & (that order, ignoring the side-effect of actually printing anything out)?

julia> if hello() && world()
         println("This would be strange, would only happen if short-circuit was right to left..")
       end
Hello

I’m looking at all options, than only “logical” && (left short-circuit), or bitwise & (seems to [must?] evaluate left, right, then the middle - the “bitwise and”).

E.g. the non-existing right short-circuit (or other possibilities…).

[Comparisons chaining, e.g. a() < b() < c() < d() … (currently) implies a() < b() && b() < c() && c() < d() …

All (or any) of the implied && could have been right-short-circuiting (or &), so you have exponentially many options just there.

I guess the semantics of chaining must imply one operator, we as language designers “choose” that one, but it could be my super-operator and that can take many forms, allowing for any combination.]

Real “logical and” is associative, McCarty added short-circuit, conflating it with control flow.

Other options, that can be faster, are:

  • right-short-circuit
  • sometimes left sometimes right, for the same code, depending on data.
  • maybe other options with even deeper implications… I’m working on that, to see if they lead to nowhere

I want the default to be maximally fast, or at least allow the implementation to consider all the above options and optimize statically for the best way if possible, dynamically if you have to.

I think I know what Julia does currently. And many C and C++ can (and cannot do… see my survey (already with some wrong answers - for Julia, in the context of if & is safe to substitute for &&, but not in C) at:

https://www.quora.com/and-and-or-Do-you-use-or-or-or-Is-faster-than-See-details-first-not-other-answers-I-also-want-beginners-to-answer-Similar

P.S. Did you know you can overload && and || in C++? One more reason to hate C++, as it disables short-circuiting and then brakes code. Who designed that, and why? This is I guess very rarely done, but I guess the optimizer needs to know, if done…

It’s a hack yes; not strictly abusing && or || as I believe that syntax started in C. But calling it “logical and” and or without associative binary relations, as logic dictates, is however wrong. C (or earlier?) is to blame for the syntax, John McCarthy for the semantics, that is short-circuiting, stating in Lisp.

I don’t like his semantics, or [linked] lists (as in Lisp), or S-expressions/non-infix (he did plan for M-expr.); other than that I really like Lisp (reads Julia).

If we consider an open source project as some kind of a block-sliding puzzle, where one performs incremental change from one working configuration to another via a PR, it is possible that this mode of operation (i.e. Incremental change) fails to explore the entire solution space. i.e. It may fail to reach some new configuration that involves simultaneously moving several blocks.

So for that reason I think it’s worth having a discussion layer that doesn’t require a PR for every suggestion.

Pretty much every language is fine with its own syntax, just as people by and large are fine with the QWERTY keyboard (despite the keys all being in silly places) and will complain if their keyboard is replaced by a (superior) DVORAK layout.

Julia prides itself on synthesising the best syntax ideas from many languages and I think this process is still ongoing.

I still have many (tens/hundreds?) hours of learning to do before I have a deep understanding of Julia, I’m currently aiming to follow in the tracks of @Ismael-VC who is learning on his feet as he submits surface-syntax PRs. I’m working through SICP first! So I’m not making suggestions expecting anyone to do anything. I have no expectation!

2 Likes

IMO exploring the space of language design by discussion is an illusion in most cases except trivial ones. The ramifications are usually not apparent until you use them — doing a PR is just a small step towards that. Also, as noted in another thread you started, the scarce resource is developer time, not the lack of willing discussants to these bikeshedding threads.

Many projects, apparently also Julia, have a culture of asking for PRs if you want a change. This has some wonderful benefits:

  1. the proposer signals some interest in the change,
  2. the PR provides a rudimentary test of the proposal,
  3. even small PRs draw people in and familiarize them with the codebase and practices.

(2) and (3) are very important. I have abandonned many PRs midway, or refrained from submitting, learning that what I want is impractical or meaningless (2). Also, many Julia contributors will ask that you do a PR for trivial changes, even when the cost of mentoring apparently exceeds what it would take for them to do it (3). When I suggested that you do a PR if you really care about his, I was serious.

(Food for thought: most people who write code for a living and have deadlines would do more than complain if you replaced their silly QWERTY with superior DVORAK without their permission. Doing this in a company would get you fired.)

3 Likes

In this particular thread, discussion has revealed that both proposals fall through (counterexamples supplied by JB and TotalVerb). So it would have been foolhardy of me to create a PR — I’m glad I chose to open a discussion rather than just dive in.

I see the merit in all three points you make — I just haven’t yet got anything to the point where it is suitable for a PR. If preliminary discussion is stage 1 and PR is stage 2, I haven’t yet proposed something ready for stage 2.

Also, many Julia contributors will ask that you do a PR for trivial changes, even when the cost of mentoring apparently exceeds what it would take for them to do it (3). When I suggested that you do a PR if you really care about his, I was serious.

I’m very grateful to the dev community for doing this, it’s a super way of teaching!

(Food for thought: most people who write code for a living and have deadlines would do more than complain if you replaced their silly QWERTY with superior DVORAK without their permission. Doing this in a company would get you fired.)

Conversely if the entire company acts as a unit, gets their heads together, says ‘hey, if we collectively take a hit for a couple of months and put ourselves through some degree of frustration, we come out 20% more productive per year if we make the switch’ … then progress has been made!

i.e. should we not seek remedy for this ugly situation, rather than simply accept it? It is around us everywhere in the world. The structure we create becomes an obstacle for an improved structure; as it gains momentum it loses the ability to change direction. I think Julia will gain a huge amount of momentum over the next few years, with universities switching out MatLab and IPython en-masse. I think 1.0 will be a pivotal point — a public declaration of stability and readiness. Can Julia somehow protect itself against the QWERTY syndrome?

Please don’t take away this conclusion from this thread. The primary reason to encourage people to write PR’s is to ensure that the costs of their brainstorming are paid by them rather than by the other developers who have to read their comments.

Maybe we should split out these kinds of discussions from “Development” into a “python-ideas” kind of category where anything goes?

5 Likes

There does seem to be a proposal on the table that has support from at least a few people, that of @jeff.bezanson, with a single ? for a short control-flow operator.
I think that just needs someone to invest the time to write a PR, and see if it does get accepted.
A related question with that proposal, is whether && and || should then no longer accept expressions on the RHS that don’t return a Bool, which would need first a deprecation for a cycle.

I’m up for implementing cond ? expr

It will take me a while as I’m going to be slow and clumsy in the beginning, so if anyone wants it ASAP then go for it!

The primary reason to encourage people to write PRs is to ensure that the costs of their brainstorming are paid by them rather than by the other developers who have to read their comments.

Sure, an organism seeks to minimise it’s overall (appropriately weighted) cost function. But it seems a bit futile to do a lap on an exercise bike just to earn credit to say something. Pedalling should generate motion to engage the reward system.

As for the cost, I don’t want to be chewing up anyone’s time. I would have thought the cost would be higher if I go ahead with a PR, because that creates discussion on the Github Issue Tracker – surely that’s going to eat more dev-joules. Also it creates clutter – an issue/PR that will immediately be closed/rejected. Isn’t the idea to keep the core clean, taking every opportunity to move activity outwards? I am new to collaborative coding so maybe I’ve got things out of proportion…

Looks like maybe I’m making some wrong assumption as regards the purpose of these forums. I thought the idea is:

  • for the heavy lifting we have Github Issue Tracker (core devs spend most of their time here)
  • for more general discussion / brainstorming we have the discourse forums (core devs keep an eye on these)
  • for coffeebreak style / ephemeral chitchat and help we have Gitter (not so many core devs here)

i.e. Some kind of 3-tier system

I’m still not convinced that floating the proposal was a poor choice. Rather than waste my own time with a flawed PR and then dev-time scrutinizing it, I can have a crack at something that is well motivated. So I think the real question is: where to float such a discussion?

I like the idea of a “brainstorming” category. I think there should be a place for brainstorming; there is value in it.

1 Like

I don’t think the syntax x ? y:z is a serious problem; it currently parses as a ternary operator with no range, and we could just keep that. For cases like this you already need parentheses, e.g. x ? (y:z) : (a:b). Furthermore, writing x ? (y:z) would be very unusual since it returns a range or nothing, which is not very useful.

My answer is (also) kind of off-topic (for main thread), to this:

I’m not sure you gain any keyboard speed.**

Taking this not literally about keyboards, making any change, say changing from you chosen language (C++?) to Julia, could have that improvement (maybe not?), or more.

Joel on software famously wrote about rewrite software is a mistake. Does that mean, Julia is only for startups? I think not, you need not rewrite, you can migrate slowly. Even from PHP, with Polyglot.jl… At least for C, C++, Python and more, is Julia the ideal migration language?

** I’m not sure, are programmers limited by keyboard speed and not thought? Maybe I am a little bit limited by my writing, e.g. right here responding, but for code, I spend more time thinking than typing. Still have heard of programmers using DVORAK and liking.

If the company forced DVORAK on all, I guess, many programmers would find themselves a new job… not sure if that applies to Julia.

This is completely missing the central point of the analogy which is to illustrate the problem of a greedy strategy working off incremental change getting stuck in local minima of the cost function. That is why we still have QWERTY.

I am sure keyboard speed is of little consequence in a typical high level programming environment, but this conversation was never about keyboards!

Then I didn’t miss it completely. My much longer text, was not on keyboards (or language design); sticking with the language you know (least resistance) fits your analogy. Changing, say to Julia might help people.

Just want to say that as a newb, not knowing about the short-circuit evaluation, I’ve been doing cond ? true : error() as a one-line check. This is obviously not very elegant, but it gets the job done. I’ll switch over to the short-circuit for now to be consistent with other code, but just want to add extra support behind cond ? error() as an option.

Speaking as a beginner, once you grok the ternary operator, I think this syntax would be immediately recognizable. In fact, I think I initially thought it would work because ternary looks like if-else, so it makes sense that just if would work as well.

2 Likes

Regarding readability:

  • If we use operators such as && or ? etc., then it’s a good idea to stick to semantics that exists in other languages, so that code is easier to read.
  • If we use keywords for this, then we could also do:
length(a) == length(b) or else raise "problem!"
length(a) != length(b) and then raise "problem!"

That is, instead of using just then and else as keywords (difficult to parse), or just and and or, we can use two keywords. We could also (as we do in elseif) combine these to the keywords orelse and andthen.

1 Like

I was thinking yesterday, that since there has been talk of Nullable{T} might end up as simply a Union{T, Void}, that if we had the cond ? expr syntax, that it could actually return a Nullable{typeof(expr)} (when the value of cond ? expr is actually used, although frequently it would just be something with a side effect such as assignment or control flow). if cond ; expr ; end type is inferred to be Union{typeof(expr), Void} already.

(This may be a crazy idea, but it seems to be nicely consistent to me)

It might be nice of have and and or for & and |, and andthen and orelse for && and ||

The if cond then statement one liner was always my favourite, and I don’t think it was disproved to be workable yet, was it? (Edit: I like it for explicit readability, I honestly don’t care at all if it’s as much typing as if cond; statement; end and more than &&).

There is some logic in leaving ? unary and binary open for whatever progress is made on Nullable syntax (though ?? could be an option there).

2 Likes

Hasn’t it been pretty much debunked that DVORAK has any actual speed advantages for users after they master either form? (But that’s beside the point)

But will this change actually make us 20% more productive? Or will .-fusing, array buffers, the type system overhaul, traits, Pkg3, the ability for precompilation to handle conditional dependencies, and dispatch on keyword arguments make us more productive? I am inclined to say that these issues are a better use of development time, so I wouldn’t want to burden any core developer whose working on anything close to this to spend even a week doing some syntax changes.

That’s why people are asking for this kind of stuff to be a PR. Even if it’s is “better” (debatable): do you think it’s work the development time? If it’s worth your time, then do it. Nobody else thinks it’s a good way to spend time.

Honestly, there are good syntax problems to explore: what’s a good syntax for traits? What about for the types for structs? etc. It’s much easier to see how discussions in those areas push the language forward than this.

It’s always about costs vs benefits.

5 Likes