Functions and variables
Sort of…
Multiple dispatch
Encapsulation
Functions are first-class citizens
No strict enforcement of immutability
has a dynamic, nominative and parametric type system
Values can be specified to be of a certain type
Types are not optional, but can be omitted
julia> 1 + 1
2
julia> 1 + 1.0
2.0
julia> 1::Int64 + 1.0::Float64
2.0
julia> (1 + 1.0)::Int64
ERROR: TypeError: typeassert: expected Int64, got Float64
julia> Int64(1 + 1.0)
2
julia> Int64(1 + 1.5)
ERROR: InexactError()
Types are compatible if and only if they are explicitly declared to be
Types are declared in a tree, where concrete types are leafs and abstract types are branch nodes
julia> supertype(Int64)
Signed
julia> supertype(supertype(Int64))
Integer
julia> supertype(supertype(supertype(Int64)))
Real
julia> supertype(supertype(supertype(supertype(Int64))))
Number
julia> supertype(supertype(supertype(supertype(supertype(Int64)))))
Any
julia> struct Point
x::Int
y::Int
end
julia> point_a = Point(1, 2)
Point(1, 2)
julia> point_a.x
1
julia> point_a.y
2
julia> struct Pointy{S<:Number}
x::S
y::S
end
julia> point_b = Pointy(1.0, 2.0)
Pointy{Float64}(1.0, 2.0)
julia> point_b.x
1.0
julia> point_a.y
2.0
julia> point_c = Pointy(1, 2.0)
ERROR: MethodError: no method matching Pointy(::Float64, ::Int64)
Closest candidates are:
Pointy(::S<:Number, ::S<:Number) where S<:Number at REPL[13]:2
There's a lot more to types
julia> function my_plus(x, y)
x + y
end
my_plus (generic function with 1 method)
julia> my_plus
my_plus (generic function with 1 method)
julia> my_plus(1, 2)
3
julia> print_squares(args...) = foreach(
arg -> println(arg ^ 2), args
)
print_squares (generic function with 1 method)
julia> print_squares(1, 2, 3)
1
4
9
julia> pow(base = 2; exponent = 3) = base ^ exponent
pow (generic function with 2 methods)
julia> pow()
8
julia> pow(3)
27
julia> pow(exponent = 2)
4
julia> my_plus(x::String, y::Any) = "$(x)$(y)"
my_plus (generic function with 2 methods)
julia> my_plus(x::String, y::Float64) = "$(y)$(x)"
my_plus (generic function with 3 methods)
julia> my_plus("Hello", 1)
"Hello1"
julia> my_plus("Goodbye", 5.0)
"5.0Goodbye"
Implement specialized methods for Array
Broadcasting
julia> pow.([1, 2, 3])
3-element Array{Int64,1}:
1
8
27
julia> broadcast(pow, [1, 2, 3])
3-element Array{Int64,1}:
1
8
27
represents its own code as a data structure of the language itself
julia> sum_one_and_one = "1 + 1"
"1 + 1"
julia> sum_one_and_one_expression = parse(sum_one_and_one)
:(1 + 1)
julia> eval(sum_one_and_one_expression)
2
julia> dump(sum_one_and_one_expression)
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol +
2: Int64 1
3: Int64 1
typ: Any
julia> sum_one_and_one_expression.args[1] = :-;
julia> eval(sum_one_and_one_expression)
0
Receive, operate on and return Expr
essions
Can’t functions exhibit this same behavior?
Macros execute when code is parsed
julia> macro my_show(x)
print("$x = ")
x
end
@my_show (macro with 1 method)
julia> @my_show 5 * 12345
5 * 12345 = 61725
Extending the language
Simplifying repetitive or error-prone tasks
Configuration and derived fields
Encode dependencies in functions
setField!
for ‘configuration fields’
deriveField!
for ‘derived fields’
julia> @dependent mutable struct Powers
base::Int
cubed::Int :base
squared::Int :base
Powers(base::Int) = setField!(new(base), :base, base)
end;
julia> calculateCubed(base::Int) = base ^ 3;
julia> calculateSquared(base::Int) = base ^ 2;
julia> Powers(5)
Powers(
base::Int64 = 5
squared::Int64 = 25
cubed::Int64 = 125
)
DSL for specifying probabilistic models over random variables
julia> FactorGraph(); # Start a new model
julia> outcome = Variable(id=:outcome);
julia> Bernoulli(outcome, 0.5);
julia> outcome
ForneyLab.Variable(:outcome, Edges:
Edge belonging to variable outcome:
( bernoulli_1.i[out] )----( NONE ).
)
Doesn’t match well with mathematical notation
Becomes cumbersome fast for larger graphs
julia> FactorGraph(); # Start a new model
julia> @RV outcome ~ Bernoulli(0.5)
ForneyLab.Variable(:outcome, Edges:
Edge belonging to variable outcome:
( bernoulli_1.i[out] )----( NONE ).
)
Built-in support for calling C and Fortran
Community supported packages for other languages (Java, Python, etc.)
Provide a libary to call, specify input and output argument types and input arguments
julia> ccall((:clock, "libc"), Int32, ())
2035418
julia> path = ccall(
(:getenv, "libc"), Cstring, (Cstring,), "SHELL"
)
Cstring(0x00007ffee95abd25)
julia> unsafe_string(path)
"/bin/zsh"
Callback mechanism using buffers
Callback can be a function!
JACKAudio.jlProvide encapsulation, can be nested and precompiled
module
… end
export
, using
, import
Packages are named following a PackageName.jl
scheme
Packages are Git repositories
Centralized metadata repository
Wrapped in Pkg
module
Specified in REQUIRE
files
julia 0.6
HttpCommon 0.4.0 0.5.0
HttpServer 0.3.0
JSON 0.16.4
Mux 0.2.3
WebSockets 0.4.0
https://pkg.julialang.org
Built-in basic testing framework Base.Test
By convention in /test
with a runtests.jl
entrypoint
Pkg.test("MyPackageName")
module MyMathTest
using Base.Test
import MyMath: square
@testset "bar" begin
@testset "integers" begin
@test square(1) === 1
@test square(2) === 4
end
@test_throws(MethodError, square("foo"))
end
end
Line coverage exportable to lcov format
Memory allocation
IDEs…
Version 1.0…
Thanks for listening!