But specialisation means different things
Every system picks its own angle/niche to specialize.
Expr & Symbol objects, etc.@time sleep(1)
In [1]:
function fib(n)
if n < 2
return n
else
return fib(n-1) + fib(n-2)
end
end
Out[1]:
In [2]:
fib(n) = n < 2 ? n : fib(n - 1) + fib(n - 2)
Out[2]:
In [3]:
fib(30)
Out[3]:
In [13]:
@time fib(26)
Out[13]:
In [5]:
A = randn(10,10)
Out[5]:
In [6]:
b = randn(10,10)
Out[6]:
In [7]:
x = A \ b
Out[7]:
In [8]:
A*x - b
Out[8]:
In [9]:
eps()
Out[9]:
In [10]:
round(A*x-b, 12)
Out[10]:
In [11]:
fft(A)
Out[11]:
In [12]:
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"
Out[12]:
In [13]:
f(1.5,2)
Out[13]:
In [14]:
f(1, "bar")
Out[14]:
In [15]:
f(1,2)
Out[15]:
In [16]:
f("foo", [1,2])
Out[16]:
In [17]:
methods(f)
Out[17]:
In [18]:
f{T<:Number}(a::T, b::T) = "a and b are both $(T)s"
Out[18]:
In [19]:
f(big(1.5),big(2.5))
Out[19]:
In [20]:
f(big(1),big(2)) #<== integer rule is more specific
Out[20]:
In [21]:
f("foo","bar") #<== still doesn't apply to non-numbers
Out[21]:
In [22]:
f(args::Number...) = "$(length(args))-ary heterogeneous call"
f{T<:Number}(args::T...) = "$(length(args))-ary homogeneous call"
Out[22]:
In [23]:
f(1)
Out[23]:
In [24]:
f(1,2,3)
Out[24]:
In [25]:
f(1,1.5,2)
Out[25]:
In [26]:
f() #==> heterogeneous because we can't bind T
Out[26]:
In [27]:
f(1,2) #<== previous 2-arg method is more specific
Out[27]:
In [28]:
f("foo") #<== doesn't apply to non-numbers
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:
In [29]:
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
In [30]:
using ModInts
In [31]:
ModInt
Out[31]:
In [32]:
ModInt{11}
Out[32]:
In [33]:
a=ModInt{11}(12345532425)
Out[33]:
In [34]:
b=ModInt{11}(23445134156)
Out[34]:
In [35]:
a+b
Out[35]:
In [36]:
a+b+b
Out[36]:
In [37]:
a+1
Out[37]:
In [38]:
2a
Out[38]:
In [39]:
2a+1
Out[39]:
In [40]:
A = map(ModInt{11}, rand(1:1000, 5,5))
Out[40]:
In [41]:
A^2
Out[41]:
In [52]:
A^10000000
Out[52]:
In [43]:
B = map(ModInt{11}, rand(1:1000, 5,5))
Out[43]:
In [44]:
A+B
Out[44]:
In [45]:
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
Out[45]:
In [46]:
foo(3,4)
Out[46]:
In [47]:
code_llvm(foo,(Int,Int))
In [48]:
using Gadfly
@plot(cos(x)/x, 5, 25)
Out[48]:
In [ ]: