Damien Gonot
Home Blog Notes About

Julia

Homepage / Notes / Computer Science / Programming Languages / Julia

Base

https://docs.julialang.org/en/v1/base/base/ Fast and computation oriented

Logging

Log: println() Pretty log: display() Log with colours: printstyled() https://docs.julialang.org/en/v1/base/io-network/#Base.printstyled

Importing

using HTTP to import packages though import HTTP works too

Keywords

…

... "splat" operator represents a sequence of arguments

add(xs...) = reduce(+, xs)

add(1, 2, 3)
6
add([1, 2, 3]...)
6

;

; is used to separate statements that are on the same line

a = 1; b = 2; a + b
3

org-babel

https://github.com/shg/ob-julia-vterm.el to use :results output, Suppressor.jl needs to be installed in Julia environment

REPL

Variables

Convention: snake case (long_variable_name) is typically used

x = 1
1

Constant

Constant variables can be defined with const

const x = 2

Primitive Types

Booleans

true / false

true
true
false
false

Integers

Int or UInt for unsigned (positive integers only) Comes in Int8, Int16, Int32, Int64 and Int128 sizes Julia will default to the processor's size (32/64-Bit) by default if not specified

Floats (decimals)

Float16, Float32, Float64

Complex Numbers

n = 1 + 2im
n + 1
2 + 2im

Rational Numbers

1 // 3 + 1 // 3
2//3

Strings

Double quotes for strings:

"Damien"
Damien

Characters

Single quotes (apostrophes) for single char:

'd'
d

Numbers

1 + 1
2

Parsing

Parse integer from strings

parse(Int64, "1337")
1337

Parse float from strings

parse(Float64, "13.37")
13.37

Ranges

collect(1:10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Min / Max

Min

min() returns the minimum from any number of arguments

min(2, 3)
2
min(2, 3, 4)
2

Or using the splat operator, to expand an array to the arguments:

min([2, 3, 4]...)
2

More efficient way and avoiding the splat operator using minimum():

minimum([2, 3, 4])
2

Max

Similar for max() and maximum():

max(2, 3, 4)
4
maximum([2, 3, 4])
4

Extrema

A useful function is extrema() that returns a tuple with the min and max

extrema([2, 3, 4])
(2, 4)
extrema(1:99)
(1, 99)

Strings

https://docs.julialang.org/en/v1/base/strings/ Double quotes are always used for strings, single quotes are used for chars

Concatenation

name = "Damien"
string("My name is ", name)
My name is Damien
name = "Damien"
"My name is " * name
My name is Damien

Interpolation

name = "Damien"
"My name is $name"
My name is Damien
"1 + 1 = $(1 + 1)"
1 + 1 = 2

Split

split("x,y,z", ",")
SubString{String}["x", "y", "z"]

Join

join(["x", "y", "z"], "\n")
x
y
z

Starts With

startswith("bonjour", "bon")
true

Ends With

endswith("bonjour", "soir")
false

Contains

contains("hello", "x")
false

Strip

Remove leading and trailing characters from str (by default whitespace characters)

strip("     hello")
hello

Can remove a specific character

strip("hello!", '!')
hello

Or a vector of characters

strip(": hello!", [':', ' ', '!'])
hello

Chomp

Removes trailing newline

chomp("hello\nworld\n")
hello
world

Regex Match

match(r"value = (.*)", "value = 1337")
RegexMatch("value = 1337", 1="1337")
match(r"value = (.*)", "value = 1337").captures
Union{Nothing, SubString{String}}["1337"]
match(r"value = (.*)", "value = 1337").captures |> first
1337

Find

Find First

findfirst("Julia", "I love Julia but Julia doesn't love me")
8:12

Find Last

findlast("Julia", "I love Julia but Julia doesn't love me")
18:22

Find Next

findnext("Julia", "I love Julia but Julia doesn't love me", 1)
8:12
findnext("Julia", "I love Julia but Julia doesn't love me", 9)
18:22

Find Prev

findprev("Julia", "I love Julia but Julia doesn't love me", 1)
nothing
findprev("Julia", "I love Julia but Julia doesn't love me", 17)
8:12

Replace

replace("hello NAME", "NAME" => "Damien")
hello Damien

Data Structures

Vector is a 1-dimensional array, Matrix a 2-dimensional array

Tuples

Immutable, ordered, fixed-length

(1, 2)
(1, 2)
t = (9, 10)
t[1]
9

Named Tuples

route = (origin = "Montreal", destination = "Toronto")
route.origin
Montreal
route[:origin]
Montreal
(; origin, destination) = route
origin
Montreal

Arrays

[1, 2, 3]
[1, 2, 3]

Matrix

[1 2 3; 4 5 6]
[1 2 3; 4 5 6]
Horizontal Concatenation
hcat([1, 2, 3], [4, 5, 6])
[1 4; 2 5; 3 6]
a1 = [1, 2, 3]
a2 = [4, 5, 6]
[a1 a2]
[1 4; 2 5; 3 6]

Push / Pop / Append

array = []

# pushing an element to an array
push!(array, "element")

# remove last element from array
pop!(array)

# appending another array to an array
append!(array, [1, 2, 3])
Any[1, 2, 3]

Length / Size

length([1, 2, 3])
3
size([1, 2, 3])
(3,)
size([1 2 3; 4 5 6])
(2, 3)

Zeros / Ones / Rand(n)

Fill an array with n zeros:

zeros(5)
[0.0, 0.0, 0.0, 0.0, 0.0]

Fill an array with n zeros with Type specified:

zeros(Int, 5)
[0, 0, 0, 0, 0]

For 2D/3D… arrays:

zeros(Int, 5, 2)
[0 0; 0 0; 0 0; 0 0; 0 0]

Same thing with ones:

ones(Int, 5)
[1, 1, 1, 1, 1]

And random numbers:

rand(5)
[0.20655599984205453, 0.764336425218688, 0.707929049283852, 0.5403245301033117, 0.5747141117006983]

Using standard Normal:

randn(5)
[1.2611015684267128, 0.5431280372799115, -1.0866220141038392, 0.5592503716247522, -0.19501274806221938]

Accessing Values

Single Element
xs = [5, 10, 15]
xs[1]
5
m = [5 10 15; 20 25 30]
m[2,2]
25
Range of Elements

Using end

xs = [5, 10, 15, 20, 25]
xs[3:end]
[15, 20, 25]
By column
m = [5 10 15; 20 25 30]
m[:,1]
[5, 20]
By row
m = [5 10 15; 20 25 30]
m[1,:]
[5, 10, 15]

Concatenation

vcat([1, 2], [3, 4])
[1, 2, 3, 4]
a1 = [1, 2]
a2 = [3, 4]
[a1; a2]
[1, 2, 3, 4]

Filter

filter(x -> x < 5, 1:10)
[1, 2, 3, 4]

List Comprehensions

[x^2 for x = 1:10]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Resources

https://blog.lojic.com/2020/12/26/comprehensions-in-julia.html

End

['a', 'b', 'c'][end]
c

Sort

[3, 2, 1] |> sort
[1, 2, 3]
Sort by
sort([Dict("x" => 3, "y" => 'a'), Dict("x" => 2, "y" => 'b'), Dict("x" => 1, "y" => 'c')], by = i -> i["x"])
Dict{String, Any}[Dict("x" => 1, "y" => 'c'), Dict("x" => 2, "y" => 'b'), Dict("x" => 3, "y" => 'a')]
Reverse sort
sort([1, 2, 3], rev = true)
[3, 2, 1]

Destructuring

a, b, c = [1, 2, 3]
b
2
a, b... = [1, 2, 3]
b
[2, 3]

Delete Element From Array

deleteat!([1, 2, 3], 1)
[2, 3]

Matrix to Vector

matrix = [1 2 3; 4 5 6]
matrix |> vec
[1, 4, 2, 5, 3, 6]

Vector to Matrix

vector = [1, 2, 3, 4]
vector |> permutedims
[1 2 3 4]

Transpose Matrix

matrix = [1 3; 2 4]
matrix |> transpose
[1 2; 3 4]

' seems to be a shorthand for transpose:

matrix = [1 3; 2 4]
matrix'
[1 2; 3 4]

Circshift

circshift(1:9, 1)
[9, 1, 2, 3, 4, 5, 6, 7, 8]
circshift(1:9, -1)
[2, 3, 4, 5, 6, 7, 8, 9, 1]

Sets

No duplicate elements

Set([1, 2, 3, 3])
Set([2, 3, 1])

Dict

dict = Dict("key" => "value")

dict["key"]
value

Functions

https://docs.julialang.org/en/v1/manual/functions/

Basic syntax:

function f(x, y)
    x + y
end

f(2, 3)
5

More terse syntax:

f(x, y) = x + y

f(2, 3)
5

Anonymous Functions

x -> x*2
#1

Named Arguments

function f(x; coef = 2)
    x * coef
end

f(4)
8
f(4, coef = 4)
16

Pipe Operator

[1, 2, 3] |> length
3

Vectorized Functions f.(x)

https://docs.julialang.org/en/v1/manual/functions/#man-vectorized Applies function to all elements of vector, similar to map()

f(x) = x*2

f.([1, 2, 3])
[2, 4, 6]

Even works on the |> pipe operator!

["list", "of", "string"] .|> [uppercase, reverse, length]
Any["LIST", "fo", 6]

Other

Do-Block Syntax for Function Arguments

Passing functions as arguments to other functions is a powerful technique, but the syntax for it is not always convenient. Such calls are especially awkward to write when the function argument requires multiple lines. As an example, consider calling =[map](https://docs.julialang.org/en/v1/base/collections/#Base.map)= on a function with several cases:

map(x->if x < 0 && iseven(x)
           return 0
       elseif x == 0
           return 1
       else
           return x
       end,
    [-2, -1, 0, 1, 2])
[0, -1, 1, 1, 2]

Julia provides a reserved word =do= for rewriting this code more clearly:

map([-2, -1, 0, 1, 2]) do x
    if x < 0 && iseven(x)
        return 0
    elseif x == 0
        return 1
    else
        return x
    end
end
[0, -1, 1, 1, 2]

https://docs.julialang.org/en/v1/manual/functions/#Function-composition-and-piping

Control Flow

If statement

if 1 > 2
    "1 is larger than 2"
else
    "2 is larger than 1"
end
2 is larger than 1

For loop

for i in 1:5
    println(i)
end
1
2
3
4
5

Works on strings too:

for char in "Damien"
    println(char)
end
D
a
m
i
e
n

and Dicts:

for (key, value) in Dict("France" => "Paris", "Germany" => "Berlin", "Canada" => "Ottawa")
    println(value)
end
Berlin
Ottawa
Paris

Eachindex

eachindex(['a', 'b', 'c'])
Base.OneTo(3)

While loop

i = 0
while i < 5
    println(i)
    i += 1
end
0
1
2
3
4

Break / Continue

break stops the loop

i = 0
while i < 10
    println(i)
    i += 1
    if i == 5
        break
    end
end
0
1
2
3
4

continue stops this iteration

for i in 1:5
    if i == 3
        continue
    end
    println(i)
end
1
2
4
5

Symbols

∈: in, can be typed in the REPL and Vim with \in

⊆: subset of, can be typed with \subseteq

∘: composition operator

1:10 |> sum |> sqrt
7.416198487095663
(sqrt ∘ sum)(1:10)
7.416198487095663

Cartesian Indices

https://julialang.org/blog/2016/02/iteration/

CartesianIndex(1, 1)
CartesianIndex(1, 1)
CartesianIndex(1, 1):CartesianIndex(3, 3)
CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3); CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3); CartesianIndex(3, 1) CartesianIndex(3, 2) CartesianIndex(3, 3)]

Packages

using Package will make all functions defined "exportable" by Package available to use directly

using Statistics

mean([1,2,3])
2.0

import Package means you have to type Package.function() to access each function

import Statistics

Statistics.mean([1,2,3])
2.0

Plots

http://docs.juliaplots.org/latest/

using Plots
x = 1:20; y = rand(20)
plot(x, y)
savefig("julia-plots/plot.png")

Unicode Plots

using UnicodePlots
lineplot(sin, 1:.5:20, width = 50)
        ┌──────────────────────────────────────────────────┐
      1 │⠀⠀⢀⠎⠢⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠊⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜⠉⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠│ sin(x)
        │⠀⠀⠈⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜│
        │⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠃│
        │⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠁⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡸⠀│
        │⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⢳⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀│
        │⠀⠀⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⡎⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⢱⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⢳⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀│
f(x)    │⠤⠤⠤⠤⠤⠤⠤⠼⡤⠤⠤⠤⠤⠤⠤⢼⠤⠤⠤⠤⠤⠤⠤⢵⠤⠤⠤⠤⠤⠤⠤⡮⠤⠤⠤⠤⠤⠤⠤⡧⠤⠤⠤⠤⠤⠤⠤⡧⠤⠤│
        │⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⡎⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⠀⢱⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⡜⠀⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱⠀⠀⠀⠀⠀⡎⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⢀⠇⠀⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡄⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⢸⠀⠀⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⢰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⡜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀⠀⠀⡇⠀⠀⠀⠀│
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢇⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱⠀⠀⡰⠁⠀⠀⠀⠀│
     -1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣄⠼⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⣠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠧⣠⠃⠀⠀⠀⠀⠀│
        └──────────────────────────────────────────────────┘
        ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀20⠀
        ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀x⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

Dates

using Dates

Parsing

Date("2021-01-01")
2021-01-01

Calling C

ccall(:clock, Int32, ())
5291220
ccall(:getenv, Cstring, (Cstring,), "SHELL") |> unsafe_string
/bin/zsh

Try / Catch

try
    undefined_method()
catch e
    println(e)
finally
    println("this gets printed regardless")
end
UndefVarError(:undefined_method)
this gets printed regardless

Type Annotations

Adding thing::Type ensure thing is of type Type

"Damien"::String
Damien

Typically done inside a function:

concat_string(x::String, y::String)::String = x * y
concat_string
concat_string("Hello, ", "World")
Hello, World

Fails:

concat_string("Hello, ", 9)

Files

Macros

@code_llvm

Can be used to view the actual LLVM code generated by the Julia compiler

@code_llvm 1 + 1
;  @ int.jl:87 within `+`
define i64 @"julia_+_955"(i64 signext %0, i64 signext %1) #0 {
top:
  %2 = add i64 %1, %0
  ret i64 %2
}

@test

using Test

@test 1 == 1
Test Passed
  Expression: 1 == 1
   Evaluated: 1 == 1

Tests can be wrapped in a @testset

Packages

Resources

Learn Julia in Y minutes

https://learnxinyminutes.com/docs/julia/

Think Julia: How to Think Like a Computer Scientist

https://benlauwens.github.io/ThinkJulia.jl/latest/book.html

How to Build a Deep Neural Network from Scratch with Julia

https://medium.datadriveninvestor.com/how-to-build-a-deep-neural-network-from-scratch-with-julia-862116a194c

Julia Bootcamp 2022: Julia Basics

https://www.youtube.com/watch?v=BnTYMOOPEzw

Guide for writing shell scripts in Julia

https://github.com/ninjaaron/administrative-scripting-with-julia