Julia is a dynamic language. You don't need type declarations, and can change variable types dynamically and interactively.
For working with simple numbers, arrays, and strings, its syntax is superficially similar to Matlab, Python, and other popular languages.
A = rand(10,300)
10x300 Array{Float64,2}: 0.375636 0.482139 0.361992 0.257166 … 0.754869 0.120599 0.893813 0.0686832 0.671072 0.999855 0.286798 0.425177 0.382689 0.920532 0.447454 0.0964471 0.311746 0.606187 0.941434 0.125957 0.625727 0.730125 0.227747 0.577157 0.91215 0.194293 0.209349 0.196251 0.323599 0.625352 0.834394 0.662423 0.48925 0.955718 0.510419 0.0350443 0.926088 0.385119 0.398782 … 0.715289 0.549668 0.486071 0.980887 0.427284 0.445409 0.352723 0.482097 0.747813 0.143269 0.0323402 0.766844 0.637901 0.136801 0.778503 0.5898 0.557505 0.962389 0.788106 0.258881 0.18815 0.693301 0.754942 0.42183 0.830188 0.917995 0.822675 0.96834 0.253111 0.0893574 0.638984
It has all of the usual built-in Matlab/Numpy-like linear-algebra and vector functions:
b = rand(10)
x = A \ b
B = A' * A
erf(eigvals(B)) - 2x.^2 + 4x - 6
300-element Array{Float64,1}: -5.99331 -5.96398 -5.96022 -5.96506 -5.98213 -5.99655 -5.98238 -5.98213 -5.93154 -5.97005 -5.97269 -5.97308 -5.9354 ⋮ -5.96845 -5.99352 -4.99281 -4.95339 -4.94527 -4.9767 -5.00616 -5.01051 -5.01131 -5.04615 -5.03316 -5.00371
Complex numbers and arbitrary-precision arithmetic (via MPFR), of course.
cos(big(3 + 4im))
-2.703494560307422464769480266827091348467753695567661661019265514673434246483996e+01 with 256 bits of precision - 3.851153334811777536563337123053124569704160846091637003157728595256494186490506e+00 with 256 bits of precisionim
All strings are UTF-8 encoded Unicode by default (UTF-16 and UTF-32 also supported):
matchall(r"\s[a-z]+", "α is a Grëék letter") # regex search of a Unicode string
3-element Array{SubString{UTF8String},1}: " is" " a" " letter"
Like Python 3, variable names can be Unicode, but Julia allows a somewhat wider range of codepoints in identifiers, which can be typed by LaTeX-like tab-completion \alpha[TAB]\hat[TAB]_2[TAB]\prime.
α̂₂′ = 7
ħ = 6.62606957e-34 / 2π
ẋ = ħ * α̂₂′
7.3820020773540256e-34
Unlike Python 3, Unicode math operators are parsed as infix operators, which are available for user-defined meanings:
≪(x,y) = x < 0.1*y
50 ≪ 100, 5 ≪ 100, 5 ≤ 50
(false,true,true)
const ⊗ = kron
eye(2,2) ⊗ rand(2,2)
4x4 Array{Float64,2}: 0.556894 0.861108 0.0 0.0 0.344389 0.960697 0.0 0.0 0.0 0.0 0.556894 0.861108 0.0 0.0 0.344389 0.960697
Functions can be defined in several ways, and don't require type-declarations.
# verbose form:
function foo(x)
return x + 1
end
# one-line form:
foo(x) = x + 1
# anonymous function
x -> x + 1
(anonymous function)
The first time you call a function with arguments of a particular type, Julia JIT-compiles that function specialized for that type with LLVM, which is then cached for subsequent calls for the same types.
foo(3) # compiles foo for Int arguments
4
foo(7) # re-uses compiled foo(Int)
8
foo(7.3) # compiles a different version for Float64 arguments
8.3
foo([1,2,7,9]) # compiles a different version for Array{Int,1} arguments
4-element Array{Int64,1}: 2 3 8 10
You can inspect the generated code easily at various compilation stages, to see that Julia uses the type of the arguments to infer the types of expressions and can produce C-like fast code.
code_typed(foo, (Int,)) # julia expressions with type annotations
1-element Array{Any,1}: :($(Expr(:lambda, {:x}, {{},{{:x,Int64,0}},{}}, :(begin # In[10], line 7: return (top(box))(Int64,(top(add_int))(x::Int64,1))::Int64 end::Int64))))
code_native(foo, (Int,)) # assembly code
.section __TEXT,__text,regular,pure_instructions Filename: In[10] Source line: 7 push RBP mov RBP, RSP Source line: 7 lea RAX, QWORD PTR [RDI + 1] pop RBP ret