Author

Josh Day

Published

April 13, 2021

Julia Quickstart

I’m Stuck. Where Can I Find Help?

1. Try the Julia REPL’s help mode

Type ? to enable help mode and search documentation for functions, macros, types, and variables.

2. Help mode didn’t answer your question?

Search on Julia Discourse.

3. Still stuck? Time to ask for help!

  • For common questions: Post on Julia Discourse for searchable, permanent answers
  • For unique issues: Ask on the Julia Slack community

The Julia community is helpful when you “ask good questions” with clear context.


Working with Arrays

Creating Vectors

x = [1, 2, 3, 4]

# A "Range" doesn't store the values between 1 and 4.
y = 1:4

collect(y)  # `1:4` -> `[1, 2, 3, 4]`
4-element Vector{Int64}:
 1
 2
 3
 4
# 1 to 100 with a step size of 3: [1, 4, 7, ..., 94, 97, 100]
1:3:100
1:3:100

Creating Matrices

# Row-vector (1 x 4)
[1 2 3 4]
1×4 Matrix{Int64}:
 1  2  3  4
# Matrix (2 x 3)
[1 2 3 ; 3 4 5]
2×3 Matrix{Int64}:
 1  2  3
 3  4  5
# Matrix (100 x 3) of random Normal(0, 1) samples
randn(100, 3)
100×3 Matrix{Float64}:
 -0.985363   -0.466534   -0.876464
 -0.0422661  -0.175125    1.08556
 -0.105457   -0.432865    0.87296
  0.790322    0.481985    0.168866
  0.517563    0.922635    0.0815407
 -1.06749    -0.243647   -0.509399
 -0.865323    0.26347     0.97255
  0.742171   -0.274287    1.4255
 -0.335497    0.792262   -0.238931
  2.42671    -1.48814     0.314298
  ⋮                      
 -0.538429   -2.67803     0.0436566
 -0.886804   -0.319647   -0.799545
  1.39133     0.0449793  -1.93855
  2.89395     1.10963    -0.887508
  0.294439    0.257085    0.759522
 -0.389809    1.63385     0.0144626
 -0.913126   -0.348076   -0.40316
 -0.190158   -0.790741   -0.51075
 -0.382096    0.930446   -0.324713

Indexing (1-Based)

Julia uses 1-based indexing, unlike languages such as Python and C.

x = rand(100, 2)

x[3, 2]  # retrieve 3rd row of column 2
0.2608474451752014

Arrays are Column-Major

Data in matrices are stored with column elements adjacent in memory.

x = rand(100, 2)

x[105] == x[5, 2]
true

Working With Strings

Key differences from other languages:

  • " creates strings
  • 's' creates character literals
  • String concatenation uses *:
"Hello, " * "World!"
"Hello, World!"
  • String interpolation uses $:
x = "World!"
"Hello, $x"
"Hello, World!"
  • String macros change interpretation:
r"[a-z]"  # I'm a regular expression!
r"[a-z]"
html"<div>I'm html</div>"  # I'm HTML!
I'm html

How do I Find/Install/Load Packages?

Finding Packages

JuliaHub helps discover packages. Quality packages typically exhibit:

  • Active development (check GitHub’s pulse feature)
  • Quality documentation (understandable and thorough)
  • Community interest (high Watch, Star, and Fork counts on GitHub)

Installing Packages

Use Pkg Mode in the REPL by pressing ]:

(@v1.7) pkg> add DataFrames, StatsBase

Loading Packages

using DataFrames, StatsBase

# Only bring certain names into the namespace
using StatsBase: countmap, zscore

Using Environments

Create isolated package environments:

] activate <dir>

This generates:

  • Project.toml: User-specified desired packages and version bounds
  • Manifest.toml: Julia’s record of actually installed packages

What are Types?

Everything in Julia has a type:

typeof(1)
Int64

Types can be parameterized. A vector of 64-bit integers is Array{Int64, 1}:

typeof([1,2,3])
Vector{Int64} (alias for Array{Int64, 1})

Following Int64 up the type hierarchy reaches Any:

for T in [Int64, Signed, Integer, Real, Number]
    println(supertype(T))
end
Signed
Integer
Real
Number
Any

Abstract types define sets of concrete types. You can instantiate Int64 but not Real.


What is Multiple Dispatch?

Multiple dispatch calls different code based on argument types. This is a core strength of Julia.

f(x::Int) = 1
f(x::Float64) = 2

println(f(1))    # 1
println(f(1.0))  # 2
1
2

Type annotations restrict allowed types but aren’t necessary for functionality:

function f(x::Type1, y::Type2, z::Type3)
    # big computation
end

function f(x, y, z)
    # big computation
end

Julia’s JIT compiler creates specialized methods for each type combination, yielding identical performance either way.


What is Broadcasting?

Broadcasting applies functions to multiple inputs simultaneously by adding a dot .

sin([1,2,3])
MethodError: no method matching sin(::Vector{Int64})
The function `sin` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  sin(::Irrational{:π})
   @ Base mathconstants.jl:146
  sin(::Float16)
   @ Base math.jl:1526
  sin(::Missing)
   @ Base math.jl:1548
  ...

Stacktrace:
 [1] top-level scope
   @ ~/work/juliafordatascience.com/juliafordatascience.com/posts/from_ghost/2021-04-13-quickstart/index.qmd:218
sin.([1,2,3])
3-element Vector{Float64}:
 0.8414709848078965
 0.9092974268256817
 0.1411200080598672

Broadcast fusion combines operations without creating temporary arrays:

x = [1,2,3]
y = [4,5,6]
z = [7,8,9]

x .+ (y .* sin.(z))
3-element Vector{Float64}:
 3.6279463948751562
 6.946791233116909
 5.472710911450539

What should I use to Code in Julia?

According to the 2021 Julia User & Developer Survey:

  • 62% use VS Code with the Julia plug-in
  • 23% use Pluto.jl
  • 21% use Vi/Vim/NeoVim
  • 17% use JupyterLab
  • 13% use Juno
  • 10% use Emacs

What are Macros?

Macros (names starting with @) are functions that operate on expressions before execution. They enable metaprogramming.

Example using @time to measure performance:

@time begin
    sleep(1)
    sleep(2)
end
  3.005215 seconds (9 allocations: 336 bytes)

Additional Resources