You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Defn
x =5# Can redefine constants which is not currently in usepi=5# Operators in brackets
(+) = f # Reassigns the operator
_ = a # Discards a
a = _ # Error# Assignment chaining# Assignment is basically binding value to variable
a = (b =5) +3# a=8, b=5
a = []
b = a # Binds b to the same array (no copy made)
c =nothing# Equivalent to None in python
Stylistic conventions
Variables are snake_case
Types, modules are PascalCase
Functions, macros are lowercase w/o underscore
Mutating functions end in !
Integers
# Types
Int8, UInt8, Int128, Bool, Float16, Float64
# Size is arch dependenttypeof(1) # Int64 in 64 bit# Diff base
a =0x123# typeof returns UInt
b =0b101011
c =0o1723
d =-0x23# Max/min repr valuestypemin(Int32)
# Floats
a =1e10
a =1.32
b =0x1p0
a =Inf
b =NaN
a =big"133444444444444444444444444"
a =BigInt(133444444444444444444444444)
# Easy poly exprs2x^2+3x +1# 2^3x = 2^(3x)# 2x^3 = 2(x^3)
a = (x-1)x
a =x(x-1) # Error due to fn application
a =2(x+y) # Works because literalzero(Float32) # 0.0f0one(Int32) # 1
Overflow results in wraparound
BigInt, BigFloat available but type promotion has to be explicitly stated
Math Operations & Functions
x / y # divide
x (division symbol) y # int divide
x \ y # inverse divide
x ^ y # powerNaN*false# 0.0false*Inf# 0.0
x (|| or &&) y # Short circuited
x +=1# Every binary op has a corresponding vectorized dot op# Unary like ! and (root) too
[1, 2, 3] ^3# Error
[1, 2, 3] .^3# Elementwise mult# Nested dot calls are fused & adjacent are converted to nested forms
x .+3.* x.^2= (+).(x, (*).(3, (^).(x, 2)))
# @. macro applies dot op to all elements inside2.* A.^2.+sin.(A) =@.2A^2+sin(A)
# Updating op too support dot
a .+= b or @. a += b = a .= a .+ b
1.+ x # Error# NaN is not equal to anythingNaN==NaN# False
[1, NaN] == [1, NaN] # Falseisequal([1, NaN], [1, NaN]) # True & should be usedisinf(), isfinite(), isnan() # Other useful funcs# Comparisons can be chained like python & dotted# Order of comparison is undefined0.< A .<11<2<=3# true1>2<=3# false# Op precedence (:x are symbols)
Base.operator_precedence(:+) # 11
Base.operator_associativity(:-) # :left# Numeric conversionsT(x) or convert(T, x) # Int8(323) - Error
x % T # Converts int types, overflows if too big w/o errorround(Int, x) =Int(round(x))
# sinpi, cospi provide better repr of sin(pi*x)
a =sinpi(x)
a =sind(x) # In degrees (default is radian)
Complex & Rational numbers
# Complex numbers1+2im
(2+3im) -1# 1 + 3im3/4im=3/ (4im)
real(), imag(), conj(), angle(), abs(), abs2() # abs squaredcomplex(a, b) # Use over a + b*im# Rational numbers (not floats!!!)# Always reduced to lowest form2//3# Constructionnumerator(), denominator()
2//3==6//9# true0//0# Error
Strings
# Char
a ='x'
b =Int(a) # 120, Int64
c ='\u0ff' or '\U10ffff'
d ='\n' or '\t'# Strings
a ="hi" or """hello"""
b ="hellllooooo \ hi"
c ="""jefej ejofefj"""
c = a[1] or a[begin] or a[end]
d = b[1:2] # Range indexing & makes a copy
e =SubString(b, 1, 2) or @views b[1:2] # Creates a view, not a copyfor c in s
println(c)
endnextind(), prevind(), eachindex() # To find valid indicescodeunit(s, i) # Access raw codeunit# Concatenation
c =string(a, ", ", b)
c = a *", "* b # * used rather than + to show noncommutativity# Interpolation
a =234
b ="$(a +1)$a"# Functionsfindfirst(c, s), findlast(c, s), findnext(c, s, i)
occursin(s1, s2)
repeat(s, times), replace(s1, func)
join(vec, s, last_s)
length(s)
# Regex
reg =r"^\s" or Regex(str)
occursin(reg, s), match(reg, s)
# Byte array literals
bal =b"hello"# UInt8 array# Version literals
ver =v"0.2"# Raw literals
r =raw"huehfu"# Extra quotation should be escaped
String supports full UTF-8
All string types are subtypes of AbstractString & all char types of AbstractChar (It is better to use these in function definitions)
Strings are immutable
Strings are byte indexed, not char indexed
Characters are 32 bit primitive
Indexing starts from 1, not 0
Not every index into a String is necessarily a valid char
Number of chars in String is not always same as last index (due to variable length encoding)
Functions
# Definitionsfunctionf(x, y)
x + y
endf(x, y) = x + y
# Callingf(2, 3)
g = f
g(2, 3)
# Arg behaviourfunctionf!(x::Vec, y::Integer)
x[1] =5# Mutates
y =7# No mutation of og object# Return types# Return type enforced and return value is convertedfunctiong(x) ::Int8
x
end# Operator fn# Except for &&, || all other can be used as fn+(1, 2, 3) # 6# Anon fn
x -> x^2+ x +1
() ->3
(x, y) -> x + y
# Tuples
a = (1, 2, 3) # Immutable, fixed length containers
b = (1,)
println(a[0])
# Named tuples
x = (a=2, b=3)
x[0] or x.a
# Destructuring
(a, b, c) = [1, 2, 3] # RHS has to be an iterable
_, _, c = [1, 2, 3]
arr[0], b = [1, 2] # arr[0] is mutated# Slurping# Assignment of a collection of remaining elements
a, b..., c ="hello"# a=h, b=ell, c=o# Argument destructuringf((x, y)) = x + y
f((2, 3))
# Property destructuringfoo((; x, y)) = x + y
foo((x=2, y=2)) # Advantage is that both structs and namedtuples can be passed# Varargs# In definitionfoo(a, b, x...) = x # x is a tuple# In caller
x = (2, 3, 4)
foo(1, x...) # a=1, b=2, x=(3, 4), the callee need not be a varargs function# Optional argsfunctionx(a, b=1, c=1)
a
endx(1)
x(1, 2)
x(1, 2, 3)
methods(x) # Shows all possible methods of fn x# Keyword argsfunctionx(a, b; c=1, d=1, kwargs...) # kwargs collects extra keyword args (a immutable key value iterator)
a
endx(1, 2, c=1, d=2)
x(1, 2, c=1, :d=>2)
# In case kwargs has same name as other keyword arg, that arg takes pref# Concise do blocks# do creates an anon fn# do a, b = 2 args & do (a, b) = tuple arg# do can capture vars from outer scope and automatically close streams, etcmap(x->x, [])
map([]) do x
x
end# Composition & piping
(f \circ g)(x) =f(g(x))
1:10|> sum |> sqrt
["a", "b"] .|> [uppercase, lowercase]
Functions are first class objects that map tuple of arguments to a return value
Not pure
No explicit return required
Values are not copied to arguments, rather are shared. Arguments act like new bindings to the values (like Python)
Mutating function identifiers end in !
Reasons to have arg types
No perf impact
Correctness & Clarity
Dispatch - can have different versions of a fn for diff arg types
Do not overly restrict types & omit when not sure
Return types are not usually used and instead automatically inferred
Operators with special names
Control Flow
# Compound exprs
z =begin
x =1
y =2
x + y
end
z = (x=1; y=2; x+y)
# Conditional evalif x < y
...elseif x > y
...else...end
a ? b : c
# Short circuits
n >=0||error("n must be positive")
# Loops
i =0while i <=3global i +=1endfor i =1:3# 1:3 is a range object...endfor i in []
...endfor i =1:2, j =3:i # Nested loop, break exits both loops...endfor (i, j) inzip([], []) ...# Exceptionsstruct Custom <:Exception
var::Symbolend# Custom exceptionthrow(DomainError(1, ""))
error("") # Stops executiontry...catch e
ifisa(e, DomainError) ...else# Used instead of extending try so as to not catch more errors...finally...end
if blocks are leaky, i.e they do not introduce a local scope. New variables defined can be used later
if blocks return values
1/0 do not convey boolean meanings
&&, || are short circuited, second exprs are not evaluated if first satisfies the operator
&, | are not short circuited
Scope
# Local scope# Constants (best used with globals, local consts are not supported)constpi=3.14const a, b =1, 2
x::Float64=2.7# Automatically a constant if globally declared
Two types - global and local
if does not introduce a new scope
Inner scopes can see variables in outer scopes
Modules
Introduce new global scopes
Variables present can't be mutated from other modules directly
Constants
Not supported by local vars
Structs are const by default
Types
# Types
(1+2)::Int# Asserts type
a::Int=1+2# Specifies/Declares type# Abstract typesabstract type Number endabstract type Signed <:Integerend# <: specifies supertype (defaults to Any)
Integer <:Number# true# Primitivesprimitive type Float16 <:AbstractFloat16end# Specify bits# Composite typesstruct Foo
bar
baz::Intendmutable struct A
a
const b::Intend
foo =Foo("", 1) # Constructor
foo.bar # ""fieldnames(Foo) # (:bar, :baz)# Type unions
IntOrStr = Union{Int, AbstractString}
Option = Union{Nothing, Int} # Like Option<T># Parametric types (types with parameters)# Compositestruct Point{T}
x::T
y::Tend
Point{AbstractString} <:Point# true
Point{<:AbstractString} # Subtypes also accepted nowPoint{Float64}(1.0, 2.0)
# Abstractabstract type Pointy{T, X} endabstract type Pointy{T<:Real} end# Guard# Tuple types
Tuple{Int, String}
Tuple{Int, Vararg{String}} # Variable arg type# Named tuple types@NamedTuple{a::Int, b::String}
@NamedTuplebegin
a::Int
b::Stringend# UnionAll types
Julia is dynamically typed, is nominative and parametric
Has method dispatch with on types of args
All concrete types are final and can only have abstract types are supertypes
All values in Julia are true objects
No compile time type exists
Variables don't have types, only values do
Abstract types
Can't be instantiated
Any is at the top of the type graph and Union{} at the bottom
Gives default impls for concrete types (make it generic)
Primitive types
Do not make your own
struct is immutable but contained objects that are mutable remain mutable. Mutables are alloc on heap
All 3 types are repr internally as DataType
Type params are invariant
Float64 <: Real but P{Float64} not subtype of P{Real}
Definition of one possible behaviour of a function is called a method
When a function is applied to a particular tuple of arguments, the most specific method applicable to those arguments is applied.
The choice of which method to execute when a function is applied is called dispatch.
Multiple dispatch used where all args are considered (unlike other langs where only first considered)
The first method definition for a function creates the function object, and subsequent method definitions add new methods to the existing function object. Creating multiple methods is called specialization
Other than explicit method decl, Julia implicitly creates methods at compile time based on arg types
Modules
module FastThings
end# Qualification
Base.sin()
Base.:+# Needs a colon for operators# Exportsmodule A
export b, C
const C =5b(x) = x
end# Using modulesusing A # Adds elements of export list to global namespaceusing.A # Load module from locally defined moduleimport A # Allows only qualified access (export list does not matter)import A as B
import A:a as b
using.A:a, b, A # Specific name imports (specify modulename itself to import it too)# Adding methodsusing.A or import.A:a # using .A:a won't work
A.a() =...# Baremodules (w/o containing Base, eval and include)baremodule A
# Submodulesmodule A
module B
import..C:a # Each . = parentendend
They are separate namespaces and introduce a global scope
Can export and import names
Can be precompiled
Can have multiple modules per file and vice versa
PascalCase and plural
Standard modules
Core - builtins
Base - base functionality
Main - top level and current module
Documentation
"Info"# Interpreted as markdownfoo(x) = x
# Enables to use raw, and other types of string including interpolation@docraw""""""f(x) = x
@doc(@doc foo!)foo # Use foo!'s documentation
Metaprogramming
Lisp style macros operating at the level of AST
Arrays
zeroes(Int8, (2, 3))
ones(...), trues(), falses()
reshape(), copy(), deepcopy()
range(), fill!()
Matrix{T}()
# Array literals
[1, 2, 3] # Tries to promote if diff types, else heterogeneous
Int8[1, 2, 3]
# Concatenation
[1:2, 4:5] # 2D array
[1:2; 4:5] # Vertically concats (1, 2, 4, 5)'
[1:2;; 4:5] # Horizontally concat (1, 2, 4, 5)# Comprehensions
[x + y for x=1:2, y=2:3if x + y ==2]
[(i,j) for i=1:3for j=1:i] # Nested loop# Generators
(i*2for i=1:10)
# Indexing
a[1, 2]
a[(1, 2)]
x[2:3, 2:end-1]
# Indexed assignment
x[2, 3] =1
x[CartesianIndex(1, 2, 3)] # Groups indices into one obj
x[[false, true], :] # Boolean indexing
x[map(ispow2, x)]
x[5] # If x is multidim, a single element is returned in column major form