Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
🔵 🔴 🟢 🟣
Julia language primer

Expressions and types

Expressions and types You can discover types of stuff using typeof.

Common types:

  • Bool
false, true
  • Char
'a', 'b', ...
  • String
"some random text" 
  • Int
1, 0, -1, ...
  • Float64
 1.1, 0, -1, ...

Types may have parameters (usually "contained type")

  • Vector{Int}
[1, 2, 5, 10]
  • Matrix{Float64}
[1.0 2.0; 2.0 1.0]
  • Tuple
(1, 2.0, "SomeLabel") 
  • Set{Int}
  • Dict{Int,String}

(default parameter value is typically Any)

Basic functionality and expectable stuff

  • Math: +, -, *, /, ^, ...

  • Logic: ==, !=, <, >, <=, >=, &&, ||, !, ...

  • Assignment: =, +=, -=, *=, ...

  • I/O: open, println, read, readlines, ...

  • Arrays: array[1], array[2:5], array[begin+1:end-1], size, length, cat, vcat, hcat, ...

Most functions are overloaded to efficiently work with multiple types of data.

Functionality is easy to discover by just Tabbing the definitions, also methods(...) and methodswith(...).

Control flow: Commands and code blocks

Typically you write 1 command per 1 line.

Commands can be separated by semicolons, and grouped using code blocks:

begin
  a = 10
  b = 20; b += 20
  a + b                # implicit return!
end

Many constructions (cycles, function definitions) start the block automatically, you only write end.

Control flow: Conditional execution

  • Traditional if:
if condition
  actions
else        # optional
  actions   # optional
end
  • Shorter inline condition:
myfunction( index<=10 ? array[index] : default_value )
  • 💡 Useful shell-like shortcuts:
a <  0  &&  (a =  0)
a > 10  &&  (a = 10)


isfinite(a) ||  @error "a is infinite, program will crash!"

Control flow: Doing stuff many times

Iteration count-based loop:

for var = iterable   # , var2 = iterable2, ...
  code(variable, variable2)
  # ...
end

Syntax with in instead of = is also supported.

Examples:

for i = 1:10
  @info "iterating!" i
end

for i = 1:10, j = 1:10
  matrix[i,j] = i*j
end

Utilities: eachindex, enumerate

Control flow: Doing stuff many times

Condition satisfaction-based loop:

    while condition
      do_something() # condition is true
    end
    # condition is false

Example:

    number = 123519
    digit_sum = 0
    while number > 0
      digit_sum += number % 10
      number ÷= 10 
    end
    @info "We've got results!" digit_sum

💡 Structured cycles!

Using functional-style loops is much less error-prone to indexing errors.

  • Transform an array:
map(sqrt, [1,2,3,4,5])
map((x,y) -> (x^2 - exp(y)), [1,2,3], [-1,0,1])
  • Summarize an array:
reduce(+, [1,2,3,4,5])
reduce((a,b) -> "$b $a", ["Use", "the Force", "Luke"])
reduce(*, [1 2 3; 4 5 6], dims=1)

Making new arrays with loops

julia> [i*10 + j for i = 1:3, j = 1:5]
3×5 Matrix{Int64}:
11   12   13   14   15
21   22   23   24   25
31   32   33   34   35

julia> join(sort([c for word in ["the result is 123", "what's happening?", "stuff"]
                    for c in word
                    if isletter(c)]))
"aaeeeffghhhiilnnpprssssttttuuw"

Control flow: subroutines (functions)

  • Multi-line function definition
function combine(a,b)
  return a + b
end
  • "Mathematical" neater definition
combine(a,b) = a + b
  • 💡 Definition with types specified (prevents errors, allows optimizations!)
function combine(a::Int, b::Int)::Int
    return a + b
end

💡💡 Control flow: subroutine overloading (methods)

  • A method for combining integers
combine(a::Int, b::Int)::Int = a + b
  • A method of the "same function" for combining strings
combine(a::String, b::String)::String = "$a and $b"

💡💡💡 Supertype hierarchy

Types possess a single supertype, which allows you to easily group multiple types under e.g. Real, Function, Type, Any, ...

This creates groups of types that are useful for restricting your functions to work on the most reasonable subsets of inputs.


julia> Int
Int64

julia> Int.super
Signed

julia> Int.super.super
Integer

julia> Int.super.super.super
Real

julia> Int.super.super.super.super
Number

julia> Int.super.super.super.super.super
Any

(Upon calling the function, Julia picks the most specific available method.)

Function arguments

  • Keyword arguments (can not be used for overloading)
function f(a, b=0; extra=0)
  return a + b + extra
end

f(123, extra=321)
  • 💡 Managing arguments en masse
euclidean(x; kwargs...) = sqrt.(sum(x.^2; kwargs...))

max_squared(args...) = maximum(args .^ 2)

Broadcasting over iterable things

  • Broadcasting operators by prepending a dot
matrix[row, :] .+= vector1 .* vector2
  • Broadcasting a function
sqrt.(1:10)
maximum.(eachcol(rand(100,100)))

x = [1,2,3,4]
x' .* x

💡 The "magic dot" is a shortcut for calling broadcast(...).

Advanced container types

  • Dictionaries (Dict{KeyType, ValueType) allow O(log n) indexing, great for lookups or keyed data structures. Contents may be typed for increased efficiency.
person = Dict("name" => "John", "surname" => "Foo", "age" => 30)
person["age"]

indexof(v::Vector) = Dict(v .=> eachindex(v))
  • 💡 Sets are key-only containers (keys are unique)
julia> x=Set([1,2,3,2,1]);
julia> println(x)
Set([2, 3, 1])

julia> push!(x,5);
julia> push!(x,5);
julia> println(x)
Set([5, 2, 3, 1])