One-line `if ... then ...` syntax

Reserved keywords are special syntax for meta-level programming (except for true and false, which are special cased).

This is the list of reserved keywords in Julia: baremodule, begin, break, catch, const, continue, do, else, elseif, end, export, false, finally, for, function, global, if, import, let, local, macro, module, quote, return, struct, true, try, using, while. Those keywords are not allowed to be used as variable names.

To be more evidently syntax, these could have been prefixed with @ such as in @for but this may have been considered too noisy.

1 Like

Exactly my point. The syntax for meta-level programming is just a list of exceptions for the open list of identifiers. I believe it is much more misleading for a novice that an word that could be a variable/function/type/etc name is actually special, and that the only way to know this is knowing the whole list of exceptions. So I do not entirely buy the point that a solution using keywords is better. Finally, in is already an exception to complementary idea that operators are restricted to non-letter symbols.


For simplicity I’d remove the in/isa exceptions to the infix operator policy rather than using the existence of some exceptions to justify others.

There’s already if a b end and a && b. Unless you are suggesting disallowing the latter (how?) the only possibility is to add a third version to the others, that may or may not supplant them (probably not.)


Just to chime in with an opinion.

I don’t always understand the obsession of writing “shorter code”, when most of the work is often having to read it multiple times.

To me, if bool then expr is much clearer than bool && expr.

Code readability is often times a good reason to not improve a package by 5% speed, so I would argue the same is the case here, that increasing the length of the statement to make the code easier to re-read is preferred.

Kind regards


Yes I am in favor of removing a && b, a || b in Julia 2.0. Julia has if expressions (rather than statements), which removes the need for such special cases.

The same applies to a ? b : c.

It would be nice to have block delimiters shorter than end, but that’s a broader issue.


if bool expr end is seldom used, because it’s even harder to read than bool && expr. I view if bool expr end as more of an artifact of how Julia parsing works than as an actual feature of the language.

a && b is certainly not going anywhere, because we still need it for regular old boolean comparison. The fact that && short-circuits is merely a performance optimization. One of the things I don’t like about bool && expr is that it is taking a performance optimization and turning it into semantics.

The other thing I don’t like about bool && expr is that it is hard to read. It’s not a matter of getting used to it—I’ve seen it plenty of times and I still think it’s harder to read than
if bool then expr.

I’ll note that if bool then expr is not quite as easy to read without syntax highlighting as it would be with syntax highlighting. Maybe it’s easier to read with real code, like this:

if isempty(x) then error("oops.")

Here’s an example with syntax highlighting (from a different language, Elm)


(Elm is a pure functional language, so if ... then statements must include an else.)


I should have specified I favor getting rid of the symbols for short-circuiting control rather than getting rid of boolean operators. Though ∨ ∧ express boolean operations more clearly IMO.

As a side note, AFAIU this work-reducing optimization can sometimes reduce throughput by putting more pressure on the branch predictor. If compute units are available then both branches can be computed simultaneously without extra cost which is helpful if the branch isn’t well predicted.

I strongly dispute this claim. The introduction of || and && in The C programming language of K&R just says:

The || operator groups left-to-right. It returns 1 if either of its operands compare unequal to zero, and 0 otherwise. Unlike |, || guarantees left-to-right evaluation: the first operand is evaluated, including all side effects; if it is unequal to 0, the value of the expression is 1.

The wikipedia page on short-circuit evaluation says nothing on this. I have a hard time believing that for combining simple relational operators (<, >, ==, and !=) over primitive data, && and || (which may incur in a jump) are more lightweight than | and & (the simplest possible operations to project in a circuit).

On the contrary, && and || short-circuiting behavior are absolutely about semantics. You can see in the K&R quote, they gave a guarantee. If the whole point of && and || was not to be short-circuiting they would not even have a reason to exist, because in C any integer greater than zero counts as true, together with > 0 you could have used | and & as replacements without loss of anything besides the short circuiting behavior.

&& and || make much easier write code like i <= n && a[i] != x, or s.tag == X && s.union_value, or basically any other condition in which the second expression would lead to an access memory violation or undefined behavior if the first expression did not guarantee that it would not. Lots of code rely on this behavior, and I do not believe this is an accident but the original intent of the short-circuiting && and ||.

I had the same experience with the unless and when of Ruby, I always though they were harder to understand than && and ||. This is anecdotal evidence. Your experience is not universal. But I would argue that && and || have the advantage that you just need to think about the truth table and you remember what they are supposed to be doing. Also anecdotal but not having English as my first language I do have much more love for symbols than words in English, which will are often already sufficiently overloaded just for someone trying to learn English.

Because it is not an work-reducing optimization.


Wow. There will certainly be some strong opposition to that. This would be terrible. I use these all the time.

How will you write

if a && b || c

I also love a ? b : c.

Shorter code can be easier to read than longer code in many cases. This is an idiom you get quickly used to.

I just wrote this in one line for convenience. I actually meant

if bool

While a good discussion is always fun, I think good to point out that this will never actually happen: PSA: Julia is not at that stage of development anymore

There will be a time when we start working on Julia 2.0, which will include some breaking changes, or we wouldn’t call it 2.0, we would just call it Julia 1.x for some value of x. At that point in time, we can consider breaking changes. But despite what it sounds like, this is not the time to make all the random changes that anyone might want to. Frankly, that time has passed for Julia and will never come again. There will probably be a few renamings of unfortunately named things. But that’s not what the 2.0 release is really about.

Your proposed changes would create such massive havoc throughout the ecosystem that probably more than 90% of code will stop working. There might not be any major packages left standing, and the reputation of the language would be devastated.

Removing && and || is basically impossible. The best you could do is introduce a more attractive alternative, and hope that it wins out over time. But so far I haven’t seen any alternatives I would use.


I agree with your point that shorter code can be easier to work with, but for me that has only been the case when:

  1. I am deepy engrossed in the code at the moment
  2. I understand the “physics” or the math/main idea behind the code

The moment one has to handle a handover or look at the code a few months down the line, then I find that often I would have to write a lot of comments to remind me about the purpose of variables/functions.

Kind regards

1 Like

I won’t take a side here, but one limitation of the && syntax that I have encountered is when trying to assign default values in a function definition:

function foo(x::AbstractVector, m::Union{Nothing,Int}=nothing)
    if m === nothing
	     m = length(x)
    return sum(x[1:m])

works fine.

function bar(x::AbstractVector, m::Union{Nothing,Int}=nothing)
    m === nothing && m = length(x)
    return sum(x[1:m])

is an

ERROR: syntax: invalid assignment location "(m === nothing) && m" around REPL[1]:10

and rightly so! m = length(x) returns length(x) (an Int), not a Bool.

I guess if you really want a one-liner and don’t like if a b end you can use the following:

function bar(x::AbstractVector, m::Union{Nothing,Int}=nothing)
    m === nothing ? m = length(x) : nothing
    return sum(x[1:m])

(Purists may prefer isnothing(m).)

You can use parentheses for that

julia> true && (x=nothing) # nothing

though I’m not sure how that’s

  Short-circuiting boolean AND.

Is this a somewhat contrived example designed only to demonstrate issues with &&? Because it seems like a Python-ism.

In Julia, you would do

function bar(x::AbstractVector, m::Int=length(x))

(Well, actually you would avoid the slice, etc, by writing two entirely separate methods.)


Whoa, since when does this work? (Since forever, probably.) You’re right: This is a leftover Python habit.


Yes, basically forever😄 It’s implemented via multiple dispatch, so you will see that it defines two separate methods.


i really hope that any IF must have an END, without (start of line) exception.
the required END really helps me with organizing and reading, so i would not like to have this pattern broken with an IF that cant have an END. I wouldnt use it in my code because it would definitely throw me off.
when it comes to && vs then, || vs or, etc. im fine with both, but i prefer typing and reading then/and/or/…
im fine with shortcut versions that dont have IF-END. why not?

1 Like

Comprehensions can have if without end, like this:

[x for x in 1:10 if iseven(x)]

But I think this is still quite clear and easy to read.

hi. thanks for pointing out this different use of if.
im still confident that everyone knows i mean “if” at the start of the line.