Beginner

Control Flow in Julia

Learn conditionals, loops, and branching in Julia with practical Docker-ready examples covering if/elseif/else, ternary expressions, for and while loops, and comprehensions

Control flow determines the order in which your program executes statements—which branches it takes and how often it repeats work. Julia provides a familiar set of structured control-flow constructs (if/elseif/else, for, while) that will feel comfortable to anyone coming from Python, MATLAB, or C.

What makes Julia interesting is that, as a multi-paradigm language, control flow is often an expression rather than a statement. An if block returns a value, the ternary operator is idiomatic, and the language leans on iteration over ranges and collections rather than manual index juggling. Combined with comprehensions and broadcasting, Julia lets you write loops that read like mathematical notation while still compiling to fast native code.

In this tutorial you will learn how to branch with conditionals, choose between short-circuit and ternary forms, iterate with for and while loops, control loops with break and continue, and replace explicit loops with comprehensions where appropriate.

Conditionals: if, elseif, else

Julia’s if statement uses the end keyword to close the block—there are no curly braces or significant indentation rules. Note that elseif is a single word.

Create a file named conditionals.jl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# if / elseif / else
temperature = 18

if temperature > 30
    println("It's hot")
elseif temperature > 15
    println("It's mild")
else
    println("It's cold")
end

# if is an expression: it returns the value of the last evaluated branch
status = if temperature > 0
    "above freezing"
else
    "freezing or below"
end
println("Water is $status")

# Conditions must be Bool — Julia does NOT treat 0 or "" as false
if isodd(7)
    println("7 is odd")
end

A key difference from C, Python, or JavaScript: Julia conditions must evaluate to a genuine Bool. Writing if 1 raises a TypeError rather than treating the number as truthy. This strictness catches a whole category of bugs.

Ternary and short-circuit expressions

For simple two-way choices, the ternary operator cond ? a : b is idiomatic and concise. Julia also lets you use the short-circuit operators && and || for control flow, not just boolean logic.

Create a file named ternary.jl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
score = 72

# Ternary operator: condition ? value_if_true : value_if_false
grade = score >= 60 ? "pass" : "fail"
println("Result: $grade")

# Short-circuit && acts like "if true, then do"
x = 10
x > 0 && println("x is positive")

# Short-circuit || acts like "if false, then do"
name = ""
isempty(name) || println("Name was provided")

# Ternary expressions can be chained (read top to bottom)
n = 0
sign_word = n > 0 ? "positive" :
            n < 0 ? "negative" : "zero"
println("$n is $sign_word")

Because && and || return the last evaluated operand, expressions like x > 0 && println(...) only run the right-hand side when needed—a compact, very Julian way to guard a single action.

For loops and ranges

Julia’s for loop iterates over any iterable: ranges, arrays, tuples, strings, dictionaries. Ranges are written with start:stop or start:step:stop and are lazy (they don’t allocate an array).

Create a file named for_loops.jl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Iterate over an inclusive range (1 through 5)
for i in 1:5
    print(i, " ")
end
println()

# Step ranges: 0, 2, 4, 6, 8, 10
for even in 0:2:10
    print(even, " ")
end
println()

# Iterate directly over a collection's elements
fruits = ["apple", "banana", "cherry"]
for fruit in fruits
    println("Fruit: $fruit")
end

# enumerate gives index + value together (indices start at 1)
for (i, fruit) in enumerate(fruits)
    println("$i. $fruit")
end

# Iterate over a dictionary's key => value pairs.
# Dicts are unordered, so sort the keys for predictable output.
scores = Dict("Alice" => 90, "Bob" => 85)
for name in sort(collect(keys(scores)))
    println("$name scored $(scores[name])")
end

Note Julia’s 1-based indexing: enumerate starts counting at 1, matching the convention used throughout the language and its scientific-computing ecosystem.

While loops, break, and continue

The while loop repeats as long as its condition is true. Use break to exit a loop early and continue to skip to the next iteration.

Create a file named while_loops.jl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Classic while loop
countdown = 3
while countdown > 0
    println("T-minus $countdown")
    global countdown -= 1   # 'global' needed at top-level script scope
end
println("Liftoff!")

# break: stop as soon as we find what we want
for n in 1:100
    if n^2 > 50
        println("First square over 50 is $(n^2) (n=$n)")
        break
    end
end

# continue: skip even numbers, print only odds
for n in 1:10
    if iseven(n)
        continue
    end
    print(n, " ")
end
println()

The global keyword inside the while loop deserves attention: in a script’s top-level scope, loop bodies introduce a new local scope, so reassigning the outer countdown requires global. Inside a function this is unnecessary—another reason Julia code is usually organized into functions.

Comprehensions: loops as expressions

Julia’s array comprehensions let you build collections declaratively, often replacing an explicit loop entirely. They support an optional filter condition, mirroring set-builder notation in mathematics.

Create a file named comprehensions.jl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Build an array of squares
squares = [x^2 for x in 1:5]
println(squares)

# Comprehension with a filter (only even numbers, then triple them)
evens_tripled = [3x for x in 1:10 if iseven(x)]
println(evens_tripled)

# Nested comprehension builds a 3x3 multiplication grid
grid = [i * j for i in 1:3, j in 1:3]
println(grid)

# Generators (no brackets) avoid allocating an intermediate array
total = sum(x^2 for x in 1:100)
println("Sum of squares 1..100 = $total")

The generator form sum(x^2 for x in 1:100) is control flow without ever materializing a list—Julia streams the values straight into sum, which is both memory-efficient and fast.

Running with Docker

1
2
3
4
5
6
7
8
9
# Pull the official image
docker pull julia:1.11-alpine

# Run each example
docker run --rm -v $(pwd):/app -w /app julia:1.11-alpine julia conditionals.jl
docker run --rm -v $(pwd):/app -w /app julia:1.11-alpine julia ternary.jl
docker run --rm -v $(pwd):/app -w /app julia:1.11-alpine julia for_loops.jl
docker run --rm -v $(pwd):/app -w /app julia:1.11-alpine julia while_loops.jl
docker run --rm -v $(pwd):/app -w /app julia:1.11-alpine julia comprehensions.jl

Expected Output

Running conditionals.jl:

It's mild
Water is above freezing
7 is odd

Running ternary.jl:

Result: pass
x is positive
0 is zero

Running for_loops.jl:

1 2 3 4 5 
0 2 4 6 8 10 
Fruit: apple
Fruit: banana
Fruit: cherry
1. apple
2. banana
3. cherry
Alice scored 90
Bob scored 85

Running while_loops.jl:

T-minus 3
T-minus 2
T-minus 1
Liftoff!
First square over 50 is 64 (n=8)
1 3 5 7 9 

Running comprehensions.jl:

[1, 4, 9, 16, 25]
[6, 12, 18, 24, 30]
[1 2 3; 2 4 6; 3 6 9]
Sum of squares 1..100 = 338350

Key Concepts

  • Conditions must be Bool — Julia rejects if 1 or if "x"; only true booleans are accepted, eliminating truthiness bugs.
  • if is an expression — branches return values, so you can assign the result of an if/else directly to a variable.
  • elseif is one word and every block (if, for, while, function) is closed with end—no braces, no indentation rules.
  • Ranges are lazy1:2:10 describes a sequence without allocating an array, making for i in 1:n cheap even for huge n.
  • Short-circuit operators double as control flowcond && action and cond || action are idiomatic guards in Julia.
  • Scope matters at top level — reassigning an outer variable inside a script-level loop needs global; this disappears inside functions.
  • Comprehensions and generators replace many loops[f(x) for x in xs if cond] and sum(f(x) for x in xs) express iteration declaratively and run fast.
  • Everything is 1-indexedenumerate, ranges, and array access all start at 1, consistent with Julia’s mathematical heritage.

Running Today

All examples can be run using Docker:

docker pull julia:1.11-alpine
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining