But specialisation means different things
Every system picks its own angle/niche to specialize.
Expr
& Symbol
objects, etc.@time sleep(1)
function fib(n)
if n < 2
return n
else
return fib(n-1) + fib(n-2)
end
end
fib (generic function with 1 method)
fib(n) = n < 2 ? n : fib(n - 1) + fib(n - 2)
fib (generic function with 1 method)
fib(30)
832040
@time fib(26)
elapsed time: 0.006557479 seconds (64 bytes allocated)
121393
A = randn(10,10)
10x10 Array{Float64,2}: -1.30976 -1.24665 -1.98481 … 1.8024 0.972884 2.22496 -1.73245 -1.06488 0.131453 -0.26486 1.31325 0.509545 0.68138 0.840067 -0.317617 0.206785 0.108507 -0.409318 0.219705 -0.924119 1.7471 0.856954 -0.59808 1.33977 -0.813242 -1.07687 -0.750896 0.423604 -0.522527 -0.225528 0.793055 -2.54525 0.557789 … 1.22375 -0.146579 -0.0398623 -0.309985 0.152875 -0.895848 1.41556 -0.894667 -0.783496 -0.4108 -0.223782 -0.600858 -0.503635 0.757326 0.356692 -0.749092 0.578509 -0.153763 -0.2358 1.58472 0.873386 -0.0380719 0.434442 0.996071 -1.0903 0.862904 -0.414622
b = randn(10,10)
10x10 Array{Float64,2}: 0.497573 -1.16141 -0.623559 … -0.405122 -0.408625 0.778652 -0.0733248 0.500723 0.0851337 0.12818 0.423034 -0.179 -0.304402 1.17565 -1.15891 -0.301865 -0.677907 0.0910984 0.551543 -0.821189 1.12574 -0.292132 -1.35895 -0.866446 2.02635 -0.584961 0.610451 0.218641 0.671659 1.04507 0.335287 -0.820849 -0.446622 … -0.170684 1.40318 -1.51586 -1.19941 1.61175 0.293387 0.0950038 1.51991 0.382434 2.0922 0.845295 0.158825 -1.6935 -0.844484 0.460787 -1.17735 0.509996 0.600545 0.733072 0.142897 -0.514896 -1.4766 0.0797037 0.200661 -1.44351 -1.02833 -0.345725
x = A \ b
10x10 Array{Float64,2}: -0.387223 -0.969381 -0.364462 … 0.727768 0.535889 -0.654995 20.1103 13.7354 -13.0452 -13.3273 -21.0828 7.63941 3.79951 3.27369 -2.4064 -2.42035 -4.36997 0.899417 -12.6121 -7.63838 7.54477 8.02675 12.319 -4.51312 2.41019 0.864194 0.171613 -2.09304 -2.15821 0.925504 -0.0433425 -0.713409 0.907706 … 1.51948 1.0485 -0.231239 -5.03231 -2.7277 3.74034 3.36796 5.6027 -2.1193 13.5295 10.4981 -9.59809 -9.56239 -14.2715 4.83205 12.2784 9.08601 -8.53129 -8.78272 -12.7905 4.04945 4.63908 1.46401 -2.22968 -2.46468 -4.65656 1.51594
A*x - b
10x10 Array{Float64,2}: -4.77396e-15 4.21885e-15 1.22125e-15 … 1.81521e-14 -3.9968e-15 -1.27676e-15 -1.11022e-16 -2.35922e-16 -1.33227e-15 1.94289e-16 5.4956e-15 4.44089e-16 2.88658e-15 3.33067e-15 1.19349e-15 5.66214e-15 1.22125e-15 5.55112e-15 -2.22045e-15 -1.33227e-15 -1.06581e-14 1.11022e-15 -4.44089e-15 -3.66374e-15 -4.44089e-16 -1.05471e-14 1.11022e-15 4.44089e-16 … -4.21885e-15 3.33067e-15 -1.9984e-15 -3.10862e-15 -1.33227e-15 2.66454e-15 -2.22045e-15 -4.88498e-15 2.22045e-16 -2.88658e-15 -7.10543e-15 3.88578e-16 4.21885e-15 4.21885e-15 2.88658e-15 9.40914e-15 -1.22125e-15 5.9952e-15 2.02616e-15 -8.32667e-17 -8.65974e-15 8.32667e-16
eps()
2.220446049250313e-16
round(A*x-b, 12)
10x10 Array{Float64,2}: -0.0 0.0 0.0 -0.0 0.0 -0.0 -0.0 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 0.0 -0.0 -0.0 -0.0 0.0 -0.0 0.0 0.0 0.0 0.0 -0.0 -0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.0 0.0 0.0 -0.0 0.0 -0.0 -0.0 -0.0 0.0 -0.0 0.0 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 0.0 0.0 -0.0 0.0 0.0 0.0 0.0 -0.0 0.0 -0.0 -0.0 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 0.0 -0.0 -0.0 0.0 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.0 0.0 0.0 -0.0 -0.0 0.0 0.0 -0.0 0.0 -0.0 0.0
fft(A)
10x10 Array{Complex{Float64},2}: 3.05301+0.0im -7.12504+9.72478im … -7.12504-9.72478im 9.83729+3.78063im 3.85146-7.76011im 1.60801+6.18073im -12.6461+1.77685im 2.93565+13.769im -8.0573-7.12585im -0.509551+7.44926im 7.97449+8.8103im -13.9814-1.56542im 6.99391-6.73352im 0.207496+8.01103im 1.95074-4.46963im 8.51634+0.0im -8.42778+0.469558im … -8.42778-0.469558im 6.99391+6.73352im 1.95074+4.46963im 0.207496-8.01103im -0.509551-7.44926im -13.9814+1.56542im 7.97449-8.8103im -12.6461-1.77685im -8.0573+7.12585im 2.93565-13.769im 9.83729-3.78063im 1.60801-6.18073im 3.85146+7.76011im
f(a, b) = "fallback"
f(a::Number, b::Number) = "a and b are both numbers"
f(a::Number, b) = "a is a number"
f(a, b::Number) = "b is a number"
f(a::Integer, b::Integer) = "a and b are both integers"
f (generic function with 5 methods)
f(1.5,2)
"a and b are both numbers"
f(1, "bar")
"a is a number"
f(1,2)
"a and b are both integers"
f("foo", [1,2])
"fallback"
methods(f)
f{T<:Number}(a::T, b::T) = "a and b are both $(T)s"
f (generic function with 6 methods)
f(big(1.5),big(2.5))
"a and b are both BigFloats"
f(big(1),big(2)) #<== integer rule is more specific
"a and b are both integers"
f("foo","bar") #<== still doesn't apply to non-numbers
"fallback"
f(args::Number...) = "$(length(args))-ary heterogeneous call"
f{T<:Number}(args::T...) = "$(length(args))-ary homogeneous call"
f (generic function with 8 methods)
f(1)
"1-ary homogeneous call"
f(1,2,3)
"3-ary homogeneous call"
f(1,1.5,2)
"3-ary heterogeneous call"
f() #==> heterogeneous because we can't bind T
"0-ary heterogeneous call"
f(1,2) #<== previous 2-arg method is more specific
"a and b are both integers"
f("foo") #<== doesn't apply to non-numbers
no method f(ASCIIString) while loading In[28], in expression starting on line 1
Mads Torgersen's paper The Expression Problem Revisited:
To which degree can your application be structured in such a way that both the data model and the set of virtual operations over it can be extended without the need to modify existing code, without the need for code repetition and without runtime type errors.
Basically you want to be able to add:
module ModInts
export ModInt
import Base: convert, promote_rule, show, showcompact
immutable ModInt{n} <: Integer
k::Int
ModInt(k) = new(k % n)
end
-{n2}(a::ModInt{n2}) = ModInt{n2}(-a.k)
+{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k+b.k)
-{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k-b.k)
*{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k*b.k)
convert{n}(::Type{ModInt{n}}, i::Int) = ModInt{n}(i)
promote_rule{n}(::Type{ModInt{n}}, ::Type{Int}) = ModInt{n}
show{n}(io::IO, k::ModInt{n}) = print(io, "$(k.k) mod $n")
showcompact(io::IO, k::ModInt) = print(io, k.k)
end # module
using ModInts
ModInt
ModInt{n} (constructor with 0 methods)
ModInt{11}
ModInt{11} (constructor with 1 method)
a=ModInt{11}(12345532425)
6 mod 11
b=ModInt{11}(23445134156)
4 mod 11
a+b
10 mod 11
a+b+b
3 mod 11
a+1
7 mod 11
2a
1 mod 11
2a+1
2 mod 11
A = map(ModInt{11}, rand(1:1000, 5,5))
5x5 Array{ModInt{11},2}: 10 7 3 8 10 7 0 7 0 1 9 5 10 8 8 2 4 10 7 5 8 1 1 9 0
A^2
5x5 Array{ModInt{11},2}: 8 6 1 8 6 9 8 4 0 5 9 10 8 5 6 5 9 0 3 7 4 9 10 3 2
A^10000000
5x5 Array{ModInt{11},2}: 4 1 9 8 3 8 9 5 8 8 9 2 7 6 1 3 1 2 3 5 1 1 3 2 9
B = map(ModInt{11}, rand(1:1000, 5,5))
5x5 Array{ModInt{11},2}: 2 8 8 5 7 1 10 5 8 4 0 5 3 6 6 1 3 5 3 8 1 3 4 7 8
A+B
5x5 Array{ModInt{11},2}: 1 4 0 2 6 8 10 1 8 5 9 10 2 3 3 3 7 4 10 2 9 4 5 5 8
foo{n}(a::ModInt{n}, b::ModInt{n}) = a^2 + 2b - 1
foo{n}(a::ModInt{n}, b::Int) = foo(a, ModInt{n}(b))
foo{n}(a::Int, b::ModInt{n}) = foo(ModInt{n}(a), b)
foo(a::Int, b::Int) = foo(ModInt{11}(a), ModInt{11}(b)).k
foo (generic function with 4 methods)
foo(3,4)
5
code_llvm(foo,(Int,Int))
define i64 @julia_foo15929(i64, i64) { top: %2 = srem i64 %0, 11, !dbg !2947 %3 = insertvalue %ModInt undef, i64 %2, 0, !dbg !2947, !julia_type !2948 %4 = call %ModInt @julia_power_by_squaring15922(%ModInt %3, i64 2), !dbg !2947, !julia_type !2948 %5 = extractvalue %ModInt %4, 0, !dbg !2947 %6 = srem i64 %1, 11, !dbg !2947 %7 = shl i64 %6, 1, !dbg !2947 %8 = srem i64 %7, 11, !dbg !2947 %9 = add i64 %8, %5, !dbg !2947 %10 = srem i64 %9, 11, !dbg !2947 %11 = add i64 %10, -1, !dbg !2947 %12 = srem i64 %11, 11, !dbg !2947 ret i64 %12, !dbg !2947 }
using Gadfly
@plot(cos(x)/x, 5, 25)
Stefan Karpinski for inspiration for most of this presentation
Stefan, with Jeff Bezanson, Viral B Shah and Alan Edelman for creating Julia
Daniel C Jones for creating Gadfly