NexusCS

Julia

Scientific computing
Quick reference for Julia - a high-performance dynamic language for scientific computing with multiple dispatch and a sophisticated type system.
featured

Getting started

Introduction

Julia is a high-performance dynamic language for scientific computing with multiple dispatch and a sophisticated type system.

Installation

# Download from julialang.org
# Or use juliaup (recommended)
curl -fsSL https://install.julialang.org | sh

Hello World

println("Hello, World!")

# Variables (dynamically typed)
x = 10
name = "Julia"

# Type annotations (optional)
y::Int64 = 42
z::Float64 = 3.14

REPL Quick Start

# Enter REPL by running `julia`

# Shell mode (type ;)
julia> ;
shell> ls

# Package mode (type ])
julia> ]
pkg> add DataFrames

# Help mode (type ?)
julia> ?
help?> println

# Back to Julia mode (backspace)

Basic Syntax

Variables & Types

# Assignment
x = 10
y = 2.5

# Multiple assignment
a, b, c = 1, 2, 3

# Type annotations
function foo(x::Int)::String
    return "Got: $x"
end

# Type assertion
x = 10::Int

Strings

# String literals
s = "Hello"
c = 'x'  # Character

# Interpolation
name = "World"
"Hello, $name"
"1 + 2 = $(1 + 2)"

# Triple-quoted strings
text = """
  Multi-line
  string
  """

# Concatenation
"Hello" * " " * "World"
string("Hello", " ", "World")

Numbers

# Integers
x = 1
y = 0x1F  # Hex
z = 0b1010  # Binary

# Floats
a = 1.0
b = 1e10
c = 2.5e-4

# Rational numbers
r = 1//2  # 1/2
3//6 == 1//2  # true

# Complex numbers
c = 1 + 2im

Arrays & Collections

Arrays (1-indexed ⚠️)

# Create arrays
arr = [1, 2, 3, 4]
arr2d = [1 2 3; 4 5 6]  # 2×3 matrix

# Indexing (1-based!)
arr[1]      # First element
arr[end]    # Last element
arr[2:4]    # Slice [2, 3, 4]

# Comprehensions
[x^2 for x in 1:10]
[x*y for x in 1:3, y in 1:3]

# Type specification
Float64[1, 2, 3]

Array Operations

# Common functions
length(arr)       # Number of elements
size(arr)         # Dimensions
push!(arr, 5)     # Append (mutates!)
pop!(arr)         # Remove last
append!(a, b)     # Extend array

# Concatenation
vcat(a, b)        # Vertical [a; b]
hcat(a, b)        # Horizontal [a b]
[a; b]            # Vertical
[a b]             # Horizontal

Broadcasting

# Element-wise operations
arr .+ 10         # Add 10 to each
arr .* 2          # Multiply each by 2
arr .^ 2          # Square each

# Broadcasting functions
sin.(arr)
f.(arr)           # Apply f to each

# Multiple arrays
a .+ b            # Element-wise add
a .* b            # Element-wise multiply

Other Collections

# Tuples (immutable)
t = (1, 2, 3)
t = 1, 2, 3       # Same
t[1]              # Access: 1

# Named tuples
nt = (x=1, y=2)
nt.x              # Access: 1

# Dictionaries
d = Dict("a" => 1, "b" => 2)
d["a"]            # Get value
d["c"] = 3        # Set value

# Sets
s = Set([1, 2, 3])
push!(s, 4)

Control Flow

Conditionals

# If statements
if x > 0
    println("positive")
elseif x < 0
    println("negative")
else
    println("zero")
end

# Ternary operator
result = x > 0 ? "pos" : "neg"

# Short-circuit evaluation
x > 0 && println("positive")
x == 0 || println("non-zero")

Loops

# For loops
for i in 1:5
    println(i)
end

for i = 1:5  # Same
    println(i)
end

# Multiple variables
for i in 1:3, j in 1:2
    println(i, j)
end

# While loops
while x < 10
    x += 1
end

# Break and continue
for i in 1:10
    i == 5 && break
    i % 2 == 0 && continue
    println(i)
end

Functions

Basic Functions

# Long form
function greet(name)
    return "Hello, $name"
end

# Short form
greet(name) = "Hello, $name"

# Anonymous functions
x -> x^2
(x, y) -> x + y

# Multiple return values
function minmax(x, y)
    return min(x, y), max(x, y)
end
a, b = minmax(3, 5)

Arguments

# Optional arguments
function power(x, n=2)
    return x^n
end
power(3)      # 9
power(3, 3)   # 27

# Keyword arguments
function plot(x, y; style="solid", color="blue")
    # ...
end
plot(x, y, color="red")

# Varargs
function sum_all(args...)
    return sum(args)
end
sum_all(1, 2, 3)  # 6

Multiple Dispatch

# Same function name, different types
f(x::Int) = "integer"
f(x::Float64) = "float"
f(x::String) = "string"

f(1)        # "integer"
f(1.0)      # "float"
f("hi")     # "string"

# Multiple arguments
g(x::Int, y::Int) = x + y
g(x::String, y::String) = x * y

# Check methods
methods(f)

Types & Structs

Type System

# Abstract types
abstract type Animal end
abstract type Pet <: Animal end

# Concrete types (immutable)
struct Point
    x::Float64
    y::Float64
end

# Mutable structs
mutable struct Person
    name::String
    age::Int
end

# Usage
p = Point(1.0, 2.0)
person = Person("Alice", 30)
person.age = 31  # OK (mutable)

Parametric Types

# Generic types
struct Container{T}
    value::T
end

# Usage
c1 = Container{Int}(42)
c2 = Container{String}("hello")
c3 = Container(3.14)  # Auto-inferred

# Type constraints
struct Pair{T<:Number}
    a::T
    b::T
end

Type Operations

# Type checking
typeof(x)         # Get type
x isa Int         # Check type
Int <: Number     # Subtype check

# Type conversion
convert(Int, 3.14)
Int(3.14)         # Error if not exact
parse(Int, "42")

# Type union
Union{Int, String}

Modules & Packages

Modules

# Define module
module MyModule
    export foo, bar

    foo() = "exported"
    bar() = "exported"
    baz() = "not exported"
end

# Using modules
using MyModule        # Import exports
MyModule.baz()        # Access non-exported

import MyModule
MyModule.foo()

import MyModule: foo  # Import specific

Package Management

# Enter package mode (])
] add DataFrames      # Install package
] rm DataFrames       # Remove
] update              # Update all
] status              # List installed

# In code
using Pkg
Pkg.add("DataFrames")
Pkg.update()
Pkg.status()

# Using packages
using DataFrames
import CSV

Performance Tips

Type Stability

# ❌ Type-unstable (slow)
function bad(n)
    x = 1
    for i in 1:n
        x = x / 2  # Int -> Float64
    end
    return x
end

# ✅ Type-stable (fast)
function good(n)
    x = 1.0      # Start as Float64
    for i in 1:n
        x = x / 2
    end
    return x
end

# Check with @code_warntype
@code_warntype bad(10)

Vectorization

# ❌ Slow (allocates intermediate arrays)
result = sin(cos(x)) .+ 3

# ✅ Fast (fused, one allocation)
result = @. sin(cos(x)) + 3
result = sin.(cos.(x)) .+ 3  # Same

# Avoid in-place when possible
x .= x .+ 1   # In-place update

Performance Annotations

# Inline hints
@inline small_function(x) = x^2
@noinline large_function(x) = # ...

# Bounds checking
@inbounds arr[i]  # Skip bounds check

# SIMD
@simd for i in 1:n
    arr[i] = i^2
end

# Timing
@time func()      # Time once
@btime func()     # Benchmark (BenchmarkTools)

Memory Tips

# Pre-allocate arrays
arr = Vector{Float64}(undef, n)
arr = zeros(Float64, n)

# Avoid global variables
const CONST_VAL = 10  # Use const

# Use views instead of copies
view(arr, 1:10)
@view arr[1:10]
arr[1:10]         # Creates copy

Metaprogramming

Expressions

# Create expressions
ex = :(x + y)
ex = quote
    x = 1
    y = 2
    x + y
end

# Inspect
dump(ex)
Meta.show_sexpr(ex)

# Interpolation
a = :x
:($a + $a)  # :(x + x)

Macros

# Define macro
macro sayhello(name)
    return :( println("Hello, ", $name) )
end

# Use macro
@sayhello "World"

# Built-in useful macros
@time expr        # Time execution
@elapsed expr     # Return time
@show x           # Print x = value
@assert cond      # Assert condition

Common Patterns

File I/O

# Read file
text = read("file.txt", String)
lines = readlines("file.txt")

# Write file
write("out.txt", "content")

# Open/close
open("file.txt", "r") do file
    for line in eachline(file)
        println(line)
    end
end

Error Handling

# Try-catch
try
    result = risky_operation()
catch e
    println("Error: $e")
finally
    cleanup()
end

# Throw errors
error("Something went wrong")
throw(DomainError(x, "must be positive"))

# Define errors
struct MyError <: Exception
    msg::String
end

List Comprehensions

# Array comprehension
[x^2 for x in 1:10]
[x for x in 1:10 if x % 2 == 0]

# Generator (lazy)
sum(x^2 for x in 1:10)

# Multi-dimensional
[x*y for x in 1:3, y in 1:3]

# Nested
[i+j for i in 1:3 for j in 1:2]

REPL & Debugging

REPL Modes

# Julia mode (default)
julia> 1 + 1

# Help mode (?)
help?> println

# Shell mode (;)
shell> ls -la

# Package mode (])
pkg> add DataFrames

# Search mode (Ctrl+R)
# Up/Down arrows for history

Debugging Tools

# Basic debugging
@show x           # Print x = value
println("x = $x")
dump(obj)         # Show structure

# Profiling
@time func()      # Time + allocations
@allocated func() # Memory only
@profile func()   # Detailed profile

# Code introspection
@code_lowered func(args)
@code_typed func(args)
@code_llvm func(args)
@code_native func(args)

Gotchas

1-Based Indexing ⚠️

arr = [1, 2, 3]
arr[1]      # First element (not arr[0]!)
arr[end]    # Last element
arr[0]      # BoundsError

# Use eachindex for iteration
for i in eachindex(arr)
    println(arr[i])
end

Copy vs Reference

# Arrays are passed by reference
a = [1, 2, 3]
b = a        # b points to same array
b[1] = 99
a[1]         # 99 ⚠️

# Make a copy
b = copy(a)
b = a[:]     # Also works

# Deep copy for nested structures
c = deepcopy(a)

Mutation Conventions

# Functions ending in ! modify arguments
sort(arr)    # Returns sorted copy
sort!(arr)   # Modifies arr in place

push!(arr, x)   # Mutates
append!(a, b)   # Mutates
filter!(f, arr) # Mutates

Global Scope

# ❌ Slow (global variable)
x = 0
for i in 1:10
    x += i  # Slow lookup
end

# ✅ Fast (use let or function)
function sum_to_10()
    x = 0
    for i in 1:10
        x += i
    end
    return x
end

Type Declarations

# Type annotation != conversion
x::Int = 3.14      # InexactError

# Use convert
x::Int = convert(Int, 3.0)  # OK

# Type declarations in function args
f(x::Int) = x^2    # Only accepts Int
f(3.14)            # MethodError ⚠️

Also see