People often like to say that Julia "walks like python, runs like C."
But this doesn't capture any of the things that have made me love the language!
Instead, let's look at three mental models and a rabbit hole (lifted from A Mental Model for Julia by Chris Rackauckas)
another perspective, excerpted from a discussion the creators of Julia that can be found here.
Karpinski: ...it's [a] very straightforward dynamic language to use. But then there's sort of this rabbit hole of advanced features that you can go down that you don't need to know right away to write useful programs, but which can help you as you find yourself doing harder and harder things.
Edelman: What happens when you start to go down this rabbit hole is you become a better programmer, something for when you used these other languages you never knew you were missing, and never knew you wanted to be. But then when you do it, you wonder how you lived without it.
x = 2π
println("Hello world, the circumferene of a circle is $x times its radius")
typeof(π)
Hello world, the circumferene of a circle is 6.283185307179586 times its radius
Irrational{:π}
# 1D, 2D (; vs _?), list comprehension, basic operations
a = [0 1; 1 3]
b = [i for i in 1:3, j in 1:3]
3×3 Array{Int64,2}: 1 1 1 2 2 2 3 3 3
a + a
2×2 Array{Int64,2}: 0 2 2 6
a = [π/2 π; 3π/2 2π]
println(sin.(a), "this is a new line: \n")
println()
println(sin(a))
a / a
a * inv(a)
? +
[1.0 1.2246467991473532e-16; -1.0 -2.4492935982947064e-16]this is a new line: [-0.2209579211114544 0.482490682615219; 0.7237360239228284 0.502778102811374]
syntax: invalid identifier name "?"
Yes, Julia uses 1-based indexing and column-major ordering (like Fortran, Matlab)
you'll get used to it...
# ranges & splatting, CartesianIndices
a = [0 1; 3 4]
x = 1:10
xy = (1,2)
f(x,y) = x+y
f(xy...)
CartesianIndices(a)
2×2 CartesianIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}: CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(2, 1) CartesianIndex(2, 2)
Unlike Python, Julia doesn't care about indentation and instead uses end
to break out of something:
1
z(x) = [x^2 for i in 1:1000]
z (generic function with 1 method)
@time z(10)
@time z(10);
0.000003 seconds (1 allocation: 7.938 KiB) 0.000003 seconds (1 allocation: 7.938 KiB)
#typeof, supertype, concrete vs abstract
t = typeof(1.0); println(t)
for i in 1:5
t = supertype(t);
println(t)
end
isabstracttype(Real)
Float64 AbstractFloat Real Number Any Any
true
#+, methods, @code_llvm
myadd(x,y) = x+y
myadd(x::Complex ,y) = real(x)+y
# myadd(y, x::Complex) = myadd(y, x)
# above line creates an infinite loop.. had to switch x and y
myadd(y, x::Complex) = myadd(x, y)
myadd (generic function with 3 methods)
println(myadd(1,2 + 3im))
println(myadd(2 + 1im, 3))
3 5
struct HistoricNumber
num::Number
ops::Int
end
HistoricNumber(num::Number) = HistoricNumber(num, 0)
import Base: +
+(a::HistoricNumber, b::HistoricNumber) = HistoricNumber(a.num + b.num, max(a.ops, b.ops) + 1)
+(a::HistoricNumber, b::Number) = HistoricNumber(a.num + b, a.ops + 1)
+(a::Number, b::HistoricNumber) = b + a
+ (generic function with 193 methods)
n = HistoricNumber(1)
for i in 1:rand(1:1000)
n += randn()
end
n
HistoricNumber(-10.41778531348284, 558)
(if there's time)
using PyCall
py"""
import pandas as pd
"""
py"pd.DataFrame($a)"
ccall(:sqrt, Float64, (Float64,), 2)
1.4142135623730951
If you're tempted to play around with Julia, the following may be of use: