Created
April 29, 2016 01:14
-
-
Save dmrd/84f53c04cf5b5d361a4dec13d7192c5e to your computer and use it in GitHub Desktop.
Notebook walking through a few Julia examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Outline\n", | |
"- Types\n", | |
"- Multiple dispatch\n", | |
"- Performance\n", | |
"- language interop\n", | |
" - C\n", | |
" - Python\n", | |
" - C++\n", | |
"- Macros\n", | |
"\n", | |
"\n", | |
"Julia is a dynamic, typed, JIT on LLVM language designed for technical computing. Familiar to users of python/matlab, but makes it much easier to go from initial prototyping to making it go fast.\n", | |
"\n", | |
"Yes, you often can make Python (with Cython/Numba/C/C++/Fortran) run as fast as Julia, but you're not going to enjoy it." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Types\n", | |
"- Dynamic & typed\n", | |
"- abstract & concrete types\n", | |
"- type inference by dataflow" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: Number isnumber LineNumberNode VersionNumber\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"No documentation found.\n", | |
"\\textbf{Summary:}\n", | |
"\\begin{verbatim}\n", | |
"abstract Number <: Any\n", | |
"\\end{verbatim}\n", | |
"\\textbf{Subtypes:}\n", | |
"\\begin{verbatim}\n", | |
"Complex{T<:Real}\n", | |
"Real\n", | |
"\\end{verbatim}\n" | |
], | |
"text/markdown": [ | |
"No documentation found.\n", | |
"\n", | |
"**Summary:**\n", | |
"\n", | |
"```julia\n", | |
"abstract Number <: Any\n", | |
"```\n", | |
"\n", | |
"**Subtypes:**\n", | |
"\n", | |
"```julia\n", | |
"Complex{T<:Real}\n", | |
"Real\n", | |
"```\n" | |
], | |
"text/plain": [ | |
"No documentation found.\n", | |
"\n", | |
"**Summary:**\n", | |
"\n", | |
"```julia\n", | |
"abstract Number <: Any\n", | |
"```\n", | |
"\n", | |
"**Subtypes:**\n", | |
"\n", | |
"```julia\n", | |
"Complex{T<:Real}\n", | |
"Real\n", | |
"```\n" | |
] | |
}, | |
"execution_count": 1, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?Number" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Int64" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"Int64" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Int64" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"typeof(1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"super(Int64) = Signed\n", | |
"super(super(Int64)) = Integer\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"Integer" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"@show super(Int64)\n", | |
"@show super(super(Int64))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3-element Array{Int64,1}:\n", | |
" 1\n", | |
" 2\n", | |
" 3" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"i64 = [1,2,3]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3-element Array{Float64,1}:\n", | |
" 1.0\n", | |
" 2.0\n", | |
" 3.0" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"f64 = [1.0, 2.0, 3.0]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3-element Array{Float16,1}:\n", | |
" 1.0\n", | |
" 2.0\n", | |
" 3.0" | |
] | |
}, | |
"execution_count": 7, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"f16 = Vector{Float16}([1, 2, 3])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3-element Array{Any,1}:\n", | |
" \"test\"\n", | |
" 1 \n", | |
" 2 " | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[\"test\", 1, 2]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"sizeof(i64) = 24\n", | |
"sizeof(f64) = 24\n", | |
"sizeof(f16) = 6\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"6" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Ability to have relatively low level control\n", | |
"@show sizeof(i64)\n", | |
"@show sizeof(f64)\n", | |
"@show sizeof(f16)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"2x5 Array{Int64,2}:\n", | |
" 1 3 5 7 9\n", | |
" 2 4 6 8 10" | |
] | |
}, | |
"execution_count": 10, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Fortran / column major ordering\n", | |
"arr = reshape(collect(1:10), (2,5))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"1" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Yes, it's 1 indexed\n", | |
"arr[1]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"10" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Use `end` instead of -1\n", | |
"arr[end]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: AbstractArray AbstractSparseArray AbstractSparseMatrix\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"No documentation found.\n", | |
"\\textbf{Summary:}\n", | |
"\\begin{verbatim}\n", | |
"abstract AbstractArray{T,N} <: Any\n", | |
"\\end{verbatim}\n", | |
"\\textbf{Subtypes:}\n", | |
"\\begin{verbatim}\n", | |
"AbstractSparseArray{Tv,Ti,N}\n", | |
"Base.LinAlg.AbstractTriangular{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.HessenbergQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRCompactWYQ{S,M<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRPackedQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.SVDOperator{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},S}\n", | |
"Base.SparseMatrix.CHOLMOD.FactorComponent{Tv,S}\n", | |
"Bidiagonal{T}\n", | |
"Core.Inference.Range{T}\n", | |
"DenseArray{T,N}\n", | |
"Diagonal{T}\n", | |
"Hermitian{T,S<:AbstractArray{T,2}}\n", | |
"Range{T}\n", | |
"SubArray{T,N,P<:AbstractArray{T,N},I<:Tuple{Vararg{Union{AbstractArray{T,1},Colon,Int64}}},LD}\n", | |
"SymTridiagonal{T}\n", | |
"Symmetric{T,S<:AbstractArray{T,2}}\n", | |
"Tridiagonal{T}\n", | |
"ZMQ.Message\n", | |
"\\end{verbatim}\n" | |
], | |
"text/markdown": [ | |
"No documentation found.\n", | |
"\n", | |
"**Summary:**\n", | |
"\n", | |
"```julia\n", | |
"abstract AbstractArray{T,N} <: Any\n", | |
"```\n", | |
"\n", | |
"**Subtypes:**\n", | |
"\n", | |
"```julia\n", | |
"AbstractSparseArray{Tv,Ti,N}\n", | |
"Base.LinAlg.AbstractTriangular{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.HessenbergQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRCompactWYQ{S,M<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRPackedQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.SVDOperator{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},S}\n", | |
"Base.SparseMatrix.CHOLMOD.FactorComponent{Tv,S}\n", | |
"Bidiagonal{T}\n", | |
"Core.Inference.Range{T}\n", | |
"DenseArray{T,N}\n", | |
"Diagonal{T}\n", | |
"Hermitian{T,S<:AbstractArray{T,2}}\n", | |
"Range{T}\n", | |
"SubArray{T,N,P<:AbstractArray{T,N},I<:Tuple{Vararg{Union{AbstractArray{T,1},Colon,Int64}}},LD}\n", | |
"SymTridiagonal{T}\n", | |
"Symmetric{T,S<:AbstractArray{T,2}}\n", | |
"Tridiagonal{T}\n", | |
"ZMQ.Message\n", | |
"```\n" | |
], | |
"text/plain": [ | |
"No documentation found.\n", | |
"\n", | |
"**Summary:**\n", | |
"\n", | |
"```julia\n", | |
"abstract AbstractArray{T,N} <: Any\n", | |
"```\n", | |
"\n", | |
"**Subtypes:**\n", | |
"\n", | |
"```julia\n", | |
"AbstractSparseArray{Tv,Ti,N}\n", | |
"Base.LinAlg.AbstractTriangular{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.HessenbergQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRCompactWYQ{S,M<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.QRPackedQ{T,S<:AbstractArray{T,2}}\n", | |
"Base.LinAlg.SVDOperator{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},S}\n", | |
"Base.SparseMatrix.CHOLMOD.FactorComponent{Tv,S}\n", | |
"Bidiagonal{T}\n", | |
"Core.Inference.Range{T}\n", | |
"DenseArray{T,N}\n", | |
"Diagonal{T}\n", | |
"Hermitian{T,S<:AbstractArray{T,2}}\n", | |
"Range{T}\n", | |
"SubArray{T,N,P<:AbstractArray{T,N},I<:Tuple{Vararg{Union{AbstractArray{T,1},Colon,Int64}}},LD}\n", | |
"SymTridiagonal{T}\n", | |
"Symmetric{T,S<:AbstractArray{T,2}}\n", | |
"Tridiagonal{T}\n", | |
"ZMQ.Message\n", | |
"```\n" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?AbstractArray # Abstract types used to create the type hierarchy, but can't instantiate them " | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Can talk about types, but don't have to\n", | |
"- Let's you write in a style closer to Python.\n", | |
"- Add types for:\n", | |
" - readability\n", | |
" - performance (e.g. use uint8 instead of int64 here)\n", | |
" - dispatching based on types" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Multiple Dispatch\n", | |
"+ dispatch: choose method based on runtime types (not static types)\n", | |
"+ multiple: based on all arguments, not just first one\n", | |
"\n", | |
"`f(a,b,c)` vs. `a.f(b,c)`\n", | |
"\n", | |
"\n", | |
"## vs. overloading\n", | |
"- Method overloading done at compile time\n", | |
"- Multiple dispatch is done based on type at runtime\n", | |
"\n", | |
"## No \"classes\" - methods defined over data types" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"4 methods for generic function <b>eig</b>:<ul><li> eig<i>{T<:Real,S}</i>(A::<b>Union{Hermitian{Complex{T<:Real},S},Hermitian{T<:Real,S},Symmetric{T<:Real,S}}</b>, args...) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/linalg/symmetric.jl#L138\" target=\"_blank\">linalg/symmetric.jl:138</a><li> eig(A::<b>SparseMatrixCSC{Tv,Ti<:Integer}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/sparse/linalg.jl#L877\" target=\"_blank\">sparse/linalg.jl:877</a><li> eig(A::<b>Union{AbstractArray{T,2},Number}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/linalg/eigen.jl#L66\" target=\"_blank\">linalg/eigen.jl:66</a><li> eig(A::<b>Union{AbstractArray{T,2},Number}</b>, B::<b>Union{AbstractArray{T,2},Number}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/linalg/eigen.jl#L152\" target=\"_blank\">linalg/eigen.jl:152</a></ul>" | |
], | |
"text/plain": [ | |
"# 4 methods for generic function \"eig\":\n", | |
"eig{T<:Real,S}(A::Union{Hermitian{Complex{T<:Real},S},Hermitian{T<:Real,S},Symmetric{T<:Real,S}}, args...) at linalg/symmetric.jl:138\n", | |
"eig(A::SparseMatrixCSC{Tv,Ti<:Integer}) at sparse/linalg.jl:877\n", | |
"eig(A::Union{AbstractArray{T,2},Number}) at linalg/eigen.jl:66\n", | |
"eig(A::Union{AbstractArray{T,2},Number}, B::Union{AbstractArray{T,2},Number}) at linalg/eigen.jl:152" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Each method may have many implementations for different combinations of arguments\n", | |
"methods(eig)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Implementing forward diff with dual numbers" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"importall Base" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"deriv (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"type Dual{T <: Real} <: Number\n", | |
" val::T\n", | |
" deriv::T\n", | |
"end\n", | |
"Dual(x::Real) = Dual(x, zero(x))\n", | |
"real(x::Dual) = x.val\n", | |
"deriv(x::Dual) = x.deriv" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"* (generic function with 139 methods)" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"+{T}(a::Dual{T}, b::Dual{T}) = Dual(real(a) + real(b), deriv(a) + deriv(b))\n", | |
"-{T}(a::Dual{T}, b::Dual{T}) = Dual(real(a) - real(b), deriv(a) - deriv(b))\n", | |
"function *{T}(a::Dual{T}, b::Dual{T})\n", | |
" av = real(a)\n", | |
" bv = real(b)\n", | |
" Dual(av * bv,\n", | |
" av * deriv(b) + bv * deriv(a)\n", | |
" )\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Dual{Int64}(30,11)" | |
] | |
}, | |
"execution_count": 18, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"x = Dual(5, 1) # derivative w.r.t self is 1\n", | |
"x * x + x # 2x + 1 -> 11" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Dual{Int64}(125,75)" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"x ^ 3" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"^(x::<b>Number</b>, p::<b>Integer</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/intfuncs.jl#L107\" target=\"_blank\">intfuncs.jl:107</a>" | |
], | |
"text/plain": [ | |
"^(x::Number, p::Integer) at intfuncs.jl:107" | |
] | |
}, | |
"execution_count": 20, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"@which x^2" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Doesn't have a conversion from real -> Dual by default" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"ename": "LoadError", | |
"evalue": "LoadError: no promotion exists for Dual{Int64} and Int64\nwhile loading In[21], in expression starting on line 1", | |
"output_type": "error", | |
"traceback": [ | |
"LoadError: no promotion exists for Dual{Int64} and Int64\nwhile loading In[21], in expression starting on line 1", | |
"" | |
] | |
} | |
], | |
"source": [ | |
"(x*3 + 5)^2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Dual{Int64}(400,120)" | |
] | |
}, | |
"execution_count": 22, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"(Dual(5) + x * Dual(3))^2 # d/dx = 6(3x + 5) -> 120" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"convert (generic function with 537 methods)" | |
] | |
}, | |
"execution_count": 23, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Can have Julia autoconvert instead of having to explicitly convert everything ourselves\n", | |
"convert{T<:Real}(::Type{Dual{T}}, x::Real) = Dual{T}(convert(T, x), zero(T))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"promote_rule (generic function with 125 methods)" | |
] | |
}, | |
"execution_count": 24, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Julia automatically handles promotions for arithmetic between subtypes of Number\n", | |
"# This tells it what to do when asked to convert T -> Dual{T}\n", | |
"promote_rule{T <: Real}(::Type{Dual{T}}, ::Type{T}) = Dual{T}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Dual{Int64}(15,3)" | |
] | |
}, | |
"execution_count": 25, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"3x" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Dual{Int64}(400,120)" | |
] | |
}, | |
"execution_count": 26, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"(5 + 3x)^2 # d/dx = 6(3x + 5) -> 120" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Interacting with Other Languages\n", | |
"- Julia was built for the scientific programming world, which means it must be able to interface cleanly with existing code" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## FFI\n", | |
"FFI examples from the Julia docs illustrating basic cases" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: ccall c_calloc AbstractChannel\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"\\begin{verbatim}\n", | |
"ccall((symbol, library) or function_pointer, ReturnType, (ArgumentType1, ...), ArgumentValue1, ...)\n", | |
"\\end{verbatim}\n", | |
"Call function in C-exported shared library, specified by \\texttt{(function name, library)} tuple, where each component is a string or symbol.\n", | |
"Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression. Alternatively, \\texttt{ccall} may also be used to call a function pointer, such as one returned by \\texttt{dlsym}.\n", | |
"Each \\texttt{ArgumentValue} to the \\texttt{ccall} will be converted to the corresponding \\texttt{ArgumentType}, by automatic insertion of calls to \\texttt{unsafe_convert(ArgumentType, cconvert(ArgumentType, ArgumentValue))}. (See also the documentation for each of these functions for further details.) In most cases, this simply results in a call to \\texttt{convert(ArgumentType, ArgumentValue)}.\n" | |
], | |
"text/markdown": [ | |
"```\n", | |
"ccall((symbol, library) or function_pointer, ReturnType, (ArgumentType1, ...), ArgumentValue1, ...)\n", | |
"```\n", | |
"\n", | |
"Call function in C-exported shared library, specified by `(function name, library)` tuple, where each component is a string or symbol.\n", | |
"\n", | |
"Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression. Alternatively, `ccall` may also be used to call a function pointer, such as one returned by `dlsym`.\n", | |
"\n", | |
"Each `ArgumentValue` to the `ccall` will be converted to the corresponding `ArgumentType`, by automatic insertion of calls to `unsafe_convert(ArgumentType, cconvert(ArgumentType, ArgumentValue))`. (See also the documentation for each of these functions for further details.) In most cases, this simply results in a call to `convert(ArgumentType, ArgumentValue)`.\n" | |
], | |
"text/plain": [ | |
"```\n", | |
"ccall((symbol, library) or function_pointer, ReturnType, (ArgumentType1, ...), ArgumentValue1, ...)\n", | |
"```\n", | |
"\n", | |
"Call function in C-exported shared library, specified by `(function name, library)` tuple, where each component is a string or symbol.\n", | |
"\n", | |
"Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression. Alternatively, `ccall` may also be used to call a function pointer, such as one returned by `dlsym`.\n", | |
"\n", | |
"Each `ArgumentValue` to the `ccall` will be converted to the corresponding `ArgumentType`, by automatic insertion of calls to `unsafe_convert(ArgumentType, cconvert(ArgumentType, ArgumentValue))`. (See also the documentation for each of these functions for further details.) In most cases, this simply results in a call to `convert(ArgumentType, ArgumentValue)`.\n" | |
] | |
}, | |
"execution_count": 27, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?ccall" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"f (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 28, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"f() = ccall( (:clock, \"libc\"), Int32, ())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"\t.section\t__TEXT,__text,regular,pure_instructions\n", | |
"Filename: In[28]\n", | |
"Source line: 1\n", | |
"\tpushq\t%rbp\n", | |
"\tmovq\t%rsp, %rbp\n", | |
"\tmovabsq\t$clock, %rax\n", | |
"Source line: 1\n", | |
"\tcallq\t*%rax\n", | |
"\tpopq\t%rbp\n", | |
"\tret\n" | |
] | |
} | |
], | |
"source": [ | |
"@code_native f() # Just a low level function call" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"gethostname (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 30, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"function gethostname()\n", | |
" hostname = Array(UInt8, 128)\n", | |
" ccall((:gethostname, \"libc\"), Int32,\n", | |
" (Ptr{UInt8}, Csize_t),\n", | |
" hostname, sizeof(hostname))\n", | |
" hostname[end] = 0; # ensure null-termination\n", | |
" return bytestring(pointer(hostname))\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"\"ddohan-mbp.corp.dropbox.com\"" | |
] | |
}, | |
"execution_count": 31, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"gethostname()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Can pass Julia functions back to C" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: cfunction IntrinsicFunction broadcast_function broadcast!_function\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"\\begin{verbatim}\n", | |
"cfunction(function::Function, ReturnType::Type, (ArgumentTypes...))\n", | |
"\\end{verbatim}\n", | |
"Generate C-callable function pointer from Julia function. Type annotation of the return value in the callback function is a must for situations where Julia cannot infer the return type automatically.\n", | |
"For example:\n", | |
"\\begin{verbatim}\n", | |
"function foo()\n", | |
" # body\n", | |
"\n", | |
" retval::Float64\n", | |
"end\n", | |
"\n", | |
"bar = cfunction(foo, Float64, ())\n", | |
"\\end{verbatim}\n" | |
], | |
"text/markdown": [ | |
"```\n", | |
"cfunction(function::Function, ReturnType::Type, (ArgumentTypes...))\n", | |
"```\n", | |
"\n", | |
"Generate C-callable function pointer from Julia function. Type annotation of the return value in the callback function is a must for situations where Julia cannot infer the return type automatically.\n", | |
"\n", | |
"For example:\n", | |
"\n", | |
"```\n", | |
"function foo()\n", | |
" # body\n", | |
"\n", | |
" retval::Float64\n", | |
"end\n", | |
"\n", | |
"bar = cfunction(foo, Float64, ())\n", | |
"```\n" | |
], | |
"text/plain": [ | |
"```\n", | |
"cfunction(function::Function, ReturnType::Type, (ArgumentTypes...))\n", | |
"```\n", | |
"\n", | |
"Generate C-callable function pointer from Julia function. Type annotation of the return value in the callback function is a must for situations where Julia cannot infer the return type automatically.\n", | |
"\n", | |
"For example:\n", | |
"\n", | |
"```\n", | |
"function foo()\n", | |
" # body\n", | |
"\n", | |
" retval::Float64\n", | |
"end\n", | |
"\n", | |
"bar = cfunction(foo, Float64, ())\n", | |
"```\n" | |
] | |
}, | |
"execution_count": 32, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?cfunction" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Ptr{Void} @0x00000003153f2570" | |
] | |
}, | |
"execution_count": 33, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"function mycompare{T}(a::T, b::T)\n", | |
" return convert(Cint, a < b ? -1 : a > b ? +1 : 0)::Cint\n", | |
"end\n", | |
"const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble}))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"4-element Array{Float64,1}:\n", | |
" -2.7\n", | |
" 1.3\n", | |
" 3.1\n", | |
" 4.4" | |
] | |
}, | |
"execution_count": 34, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"A = [1.3, -2.7, 4.4, 3.1]\n", | |
"ccall(:qsort, Void, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Void}),\n", | |
" A, length(A), sizeof(eltype(A)), mycompare_c)\n", | |
"A" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Python: PyCall\n", | |
"- Interop with Python is easy. Many Julia libraries (e.g. SymPy) wrap existing Python libs for simplicity\n", | |
"- A few crazy things, like defining Python classes IN JULIA (wut)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### SymPy example" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<script charset=\"utf-8\">(function ($, undefined) {\n", | |
"\n", | |
" function createElem(tag, attr, content) {\n", | |
"\t// TODO: remove jQuery dependency\n", | |
"\tvar el = $(\"<\" + tag + \"/>\").attr(attr);\n", | |
"\tif (content) {\n", | |
"\t el.append(content);\n", | |
"\t}\n", | |
"\treturn el[0];\n", | |
" }\n", | |
"\n", | |
" // A widget must expose an id field which identifies it to the backend,\n", | |
" // an elem attribute which is will be added to the DOM, and\n", | |
" // a getState() method which returns the value to be sent to the backend\n", | |
" // a sendUpdate() method which sends its current value to the backend\n", | |
" var Widget = {\n", | |
"\tid: undefined,\n", | |
"\telem: undefined,\n", | |
"\tlabel: undefined,\n", | |
"\tgetState: function () {\n", | |
"\t return this.elem.value;\n", | |
"\t},\n", | |
"\tsendUpdate: undefined\n", | |
" };\n", | |
"\n", | |
" var Slider = function (typ, id, init) {\n", | |
"\tvar attr = { type: \"range\",\n", | |
"\t\t value: init.value,\n", | |
"\t\t min: init.min,\n", | |
"\t\t max: init.max,\n", | |
"\t\t step: init.step },\n", | |
"\t elem = createElem(\"input\", attr),\n", | |
"\t self = this;\n", | |
"\n", | |
"\telem.onchange = function () {\n", | |
"\t self.sendUpdate();\n", | |
"\t}\n", | |
"\n", | |
"\tthis.id = id;\n", | |
"\tthis.elem = elem;\n", | |
"\tthis.label = init.label;\n", | |
"\n", | |
"\tInputWidgets.commInitializer(this); // Initialize communication\n", | |
" }\n", | |
" Slider.prototype = Widget;\n", | |
"\n", | |
" var Checkbox = function (typ, id, init) {\n", | |
"\tvar attr = { type: \"checkbox\",\n", | |
"\t\t checked: init.value },\n", | |
"\t elem = createElem(\"input\", attr),\n", | |
"\t self = this;\n", | |
"\n", | |
"\tthis.getState = function () {\n", | |
"\t return elem.checked;\n", | |
"\t}\n", | |
"\telem.onchange = function () {\n", | |
"\t self.sendUpdate();\n", | |
"\t}\n", | |
"\n", | |
"\tthis.id = id;\n", | |
"\tthis.elem = elem;\n", | |
"\tthis.label = init.label;\n", | |
"\n", | |
"\tInputWidgets.commInitializer(this);\n", | |
" }\n", | |
" Checkbox.prototype = Widget;\n", | |
"\n", | |
" var Button = function (typ, id, init) {\n", | |
"\tvar attr = { type: \"button\",\n", | |
"\t\t value: init.label },\n", | |
"\t elem = createElem(\"input\", attr),\n", | |
"\t self = this;\n", | |
"\tthis.getState = function () {\n", | |
"\t return null;\n", | |
"\t}\n", | |
"\telem.onclick = function () {\n", | |
"\t self.sendUpdate();\n", | |
"\t}\n", | |
"\n", | |
"\tthis.id = id;\n", | |
"\tthis.elem = elem;\n", | |
"\tthis.label = init.label;\n", | |
"\n", | |
"\tInputWidgets.commInitializer(this);\n", | |
" }\n", | |
" Button.prototype = Widget;\n", | |
"\n", | |
" var Text = function (typ, id, init) {\n", | |
"\tvar attr = { type: \"text\",\n", | |
"\t\t placeholder: init.label,\n", | |
"\t\t value: init.value },\n", | |
"\t elem = createElem(\"input\", attr),\n", | |
"\t self = this;\n", | |
"\tthis.getState = function () {\n", | |
"\t return elem.value;\n", | |
"\t}\n", | |
"\telem.onkeyup = function () {\n", | |
"\t self.sendUpdate();\n", | |
"\t}\n", | |
"\n", | |
"\tthis.id = id;\n", | |
"\tthis.elem = elem;\n", | |
"\tthis.label = init.label;\n", | |
"\n", | |
"\tInputWidgets.commInitializer(this);\n", | |
" }\n", | |
" Text.prototype = Widget;\n", | |
"\n", | |
" var Textarea = function (typ, id, init) {\n", | |
"\tvar attr = { placeholder: init.label },\n", | |
"\t elem = createElem(\"textarea\", attr, init.value),\n", | |
"\t self = this;\n", | |
"\tthis.getState = function () {\n", | |
"\t return elem.value;\n", | |
"\t}\n", | |
"\telem.onchange = function () {\n", | |
"\t self.sendUpdate();\n", | |
"\t}\n", | |
"\n", | |
"\tthis.id = id;\n", | |
"\tthis.elem = elem;\n", | |
"\tthis.label = init.label;\n", | |
"\n", | |
"\tInputWidgets.commInitializer(this);\n", | |
" }\n", | |
" Textarea.prototype = Widget;\n", | |
"\n", | |
" // RadioButtons\n", | |
" // Dropdown\n", | |
" // HTML\n", | |
" // Latex\n", | |
"\n", | |
" var InputWidgets = {\n", | |
"\tSlider: Slider,\n", | |
"\tCheckbox: Checkbox,\n", | |
"\tButton: Button,\n", | |
"\tText: Text,\n", | |
"\tTextarea: Textarea,\n", | |
"\tdebug: false,\n", | |
"\tlog: function () {\n", | |
"\t if (InputWidgets.debug) {\n", | |
"\t\tconsole.log.apply(console, arguments);\n", | |
"\t }\n", | |
"\t},\n", | |
"\t// a central way to initalize communication\n", | |
"\t// for widgets.\n", | |
"\tcommInitializer: function (widget) {\n", | |
"\t widget.sendUpdate = function () {};\n", | |
"\t}\n", | |
" };\n", | |
"\n", | |
" window.InputWidgets = InputWidgets;\n", | |
"\n", | |
"})(jQuery, undefined);\n", | |
"</script>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<div id=\"interact-js-shim\">\n", | |
" <script charset=\"utf-8\">\n", | |
"(function (IPython, $, _, MathJax, Widgets) {\n", | |
" $.event.special.destroyed = {\n", | |
"\tremove: function(o) {\n", | |
"\t if (o.handler) {\n", | |
"\t\to.handler.apply(this, arguments)\n", | |
"\t }\n", | |
"\t}\n", | |
" }\n", | |
"\n", | |
" var OutputArea = IPython.version >= \"4.0.0\" ? require(\"notebook/js/outputarea\").OutputArea : IPython.OutputArea;\n", | |
"\n", | |
" var redrawValue = function (container, type, val) {\n", | |
"\tvar selector = $(\"<div/>\");\n", | |
"\tvar oa = new OutputArea(_.extend(selector, {\n", | |
"\t selector: selector,\n", | |
"\t prompt_area: true,\n", | |
"\t events: IPython.events,\n", | |
"\t keyboard_manager: IPython.keyboard_manager\n", | |
"\t})); // Hack to work with IPython 2.1.0\n", | |
"\n", | |
"\tswitch (type) {\n", | |
"\tcase \"image/png\":\n", | |
" var _src = 'data:' + type + ';base64,' + val;\n", | |
"\t $(container).find(\"img\").attr('src', _src);\n", | |
"\t break;\n", | |
"\tdefault:\n", | |
"\t var toinsert = OutputArea.append_map[type].apply(\n", | |
"\t\toa, [val, {}, selector]\n", | |
"\t );\n", | |
"\t $(container).empty().append(toinsert.contents());\n", | |
"\t selector.remove();\n", | |
"\t}\n", | |
"\tif (type === \"text/latex\" && MathJax) {\n", | |
"\t MathJax.Hub.Queue([\"Typeset\", MathJax.Hub, toinsert.get(0)]);\n", | |
"\t}\n", | |
" }\n", | |
"\n", | |
"\n", | |
" $(document).ready(function() {\n", | |
"\tWidgets.debug = false; // log messages etc in console.\n", | |
"\tfunction initComm(evt, data) {\n", | |
"\t var comm_manager = data.kernel.comm_manager;\n", | |
" //_.extend(comm_manager.targets, require(\"widgets/js/widget\"))\n", | |
"\t comm_manager.register_target(\"Signal\", function (comm) {\n", | |
" comm.on_msg(function (msg) {\n", | |
" //Widgets.log(\"message received\", msg);\n", | |
" var val = msg.content.data.value;\n", | |
" $(\".signal-\" + comm.comm_id).each(function() {\n", | |
" var type = $(this).data(\"type\");\n", | |
" if (val[type]) {\n", | |
" redrawValue(this, type, val[type], type);\n", | |
" }\n", | |
" });\n", | |
" delete val;\n", | |
" delete msg.content.data.value;\n", | |
" });\n", | |
"\t });\n", | |
"\n", | |
"\t // coordingate with Comm and redraw Signals\n", | |
"\t // XXX: Test using Reactive here to improve performance\n", | |
"\t $([IPython.events]).on(\n", | |
"\t\t'output_appended.OutputArea', function (event, type, value, md, toinsert) {\n", | |
"\t\t if (md && md.reactive) {\n", | |
" // console.log(md.comm_id);\n", | |
" toinsert.addClass(\"signal-\" + md.comm_id);\n", | |
" toinsert.data(\"type\", type);\n", | |
" // Signal back indicating the mimetype required\n", | |
" var comm_manager = IPython.notebook.kernel.comm_manager;\n", | |
" var comm = comm_manager.comms[md.comm_id];\n", | |
" comm.then(function (c) {\n", | |
" c.send({action: \"subscribe_mime\",\n", | |
" mime: type});\n", | |
" toinsert.bind(\"destroyed\", function() {\n", | |
" c.send({action: \"unsubscribe_mime\",\n", | |
" mime: type});\n", | |
" });\n", | |
" })\n", | |
"\t\t }\n", | |
"\t });\n", | |
"\t}\n", | |
"\n", | |
"\ttry {\n", | |
"\t // try to initialize right away. otherwise, wait on the status_started event.\n", | |
"\t initComm(undefined, IPython.notebook);\n", | |
"\t} catch (e) {\n", | |
"\t $([IPython.events]).on('kernel_created.Kernel kernel_created.Session', initComm);\n", | |
"\t}\n", | |
" });\n", | |
"})(IPython, jQuery, _, MathJax, InputWidgets);\n", | |
"</script>\n", | |
" <script>\n", | |
" window.interactLoadedFlag = true\n", | |
" $(\"#interact-js-shim\").bind(\"destroyed\", function () {\n", | |
" if (window.interactLoadedFlag) {\n", | |
" console.warn(\"JavaScript required by Interact will be removed if you remove this cell or run using Interact more than once.\")\n", | |
" }\n", | |
" })\n", | |
" $([IPython.events]).on(\"kernel_starting.Kernel kernel_restarting.Kernel\", function () { window.interactLoadedFlag = false })\n", | |
" </script>\n", | |
"</div>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"WARNING: using Interact.select in module Main conflicts with an existing identifier.\n" | |
] | |
} | |
], | |
"source": [ | |
"using SymPy\n", | |
"using Interact" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: symbols free_symbols symbol Symbol SymbolNode is_symbolic jacobi_symbol\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"Function to create one or more symbolic objects. These are specified with a string, with commas separating different variables.\n", | |
"This function allows the passing of assumptions about the variables such as \\texttt{positive=true}, \\texttt{real=true} or \\texttt{commutative=true}. See \\href{http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions}{SymPy Docs} for a complete list.\n", | |
"Example:\n", | |
"\\begin{verbatim}\n", | |
"x,y,z = symbols(\"x, y, z\", real=true)\n", | |
"\\end{verbatim}\n" | |
], | |
"text/markdown": [ | |
"Function to create one or more symbolic objects. These are specified with a string, with commas separating different variables.\n", | |
"\n", | |
"This function allows the passing of assumptions about the variables such as `positive=true`, `real=true` or `commutative=true`. See [SymPy Docs](http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions) for a complete list.\n", | |
"\n", | |
"Example:\n", | |
"\n", | |
"```\n", | |
"x,y,z = symbols(\"x, y, z\", real=true)\n", | |
"```\n" | |
], | |
"text/plain": [ | |
"Function to create one or more symbolic objects. These are specified with a string, with commas separating different variables.\n", | |
"\n", | |
"This function allows the passing of assumptions about the variables such as `positive=true`, `real=true` or `commutative=true`. See [SymPy Docs](http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions) for a complete list.\n", | |
"\n", | |
"Example:\n", | |
"\n", | |
"```\n", | |
"x,y,z = symbols(\"x, y, z\", real=true)\n", | |
"```\n" | |
] | |
}, | |
"execution_count": 36, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?symbols" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [], | |
"text/plain": [ | |
"Interact.Slider{Int64}(Signal{Int64}(5, nactions=0),\"n\",5,0:10,true)" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [], | |
"text/plain": [ | |
"Interact.Latex(\"\",\"\\$\\$8 x \\\\left(4 x^{4} \\\\cos{\\\\left (x^{2} \\\\right )} + 20 x^{2} \\\\sin{\\\\left (x^{2} \\\\right )} - 15 \\\\cos{\\\\left (x^{2} \\\\right )}\\\\right)\\$\\$\")" | |
] | |
}, | |
"execution_count": 37, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"symx = symbols(\"x\")\n", | |
"\n", | |
"@manipulate for n = 0:10\n", | |
" latex(SymPy.diff(sin(symx^2), symx, n))\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [], | |
"text/plain": [ | |
"Interact.Slider{Int64}(Signal{Int64}(5, nactions=0),\"n\",5,0:10,true)" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"5" | |
] | |
}, | |
"execution_count": 38, | |
"metadata": { | |
"comm_id": "54a7f1f8-ef88-4d25-967f-02866623647f", | |
"reactive": true | |
}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"@manipulate for n = 0:10\n", | |
" n\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
":(let n = (Interact.widget)(0:10,\"n\")\n", | |
" display(n)\n", | |
" (map)(((n,)->begin # In[39], line 2:\n", | |
" n\n", | |
" end),(Interact.signal)(n))\n", | |
" end)" | |
] | |
}, | |
"execution_count": 39, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"macroexpand(:(@manipulate for n = 0:10\n", | |
" n\n", | |
"end))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"14 methods for generic function <b>sin</b>:<ul><li> sin(a::<b>Complex{Float16}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/float16.jl#L151\" target=\"_blank\">float16.jl:151</a><li> sin(z::<b>Complex{T<:Real}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/complex.jl#L548\" target=\"_blank\">complex.jl:548</a><li> sin(x::<b>Float64</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/math.jl#L137\" target=\"_blank\">math.jl:137</a><li> sin(x::<b>Float32</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/math.jl#L138\" target=\"_blank\">math.jl:138</a><li> sin(a::<b>Float16</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/float16.jl#L150\" target=\"_blank\">float16.jl:150</a><li> sin(x::<b>BigFloat</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/mpfr.jl#L610\" target=\"_blank\">mpfr.jl:610</a><li> sin(x::<b>Real</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/math.jl#L139\" target=\"_blank\">math.jl:139</a><li> sin<i>{Tv,Ti}</i>(A::<b>SparseMatrixCSC{Tv,Ti}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/sparse/sparsematrix.jl#L648\" target=\"_blank\">sparse/sparsematrix.jl:648</a><li> sin(a::<b>Array{SymPy.Sym,N}</b>) at <a href=\"https://github.com/jverzani/SymPy.jl/tree/d2f08e9d35f1fa84cfb5dc9427a31a4b19d51996/src/math.jl#L25\" target=\"_blank\">/Users/ddohan/.julia/v0.4/SymPy/src/math.jl:25</a><li> sin<i>{T<:Number}</i>(::<b>AbstractArray{T<:Number,1}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/operators.jl#L380\" target=\"_blank\">operators.jl:380</a><li> sin<i>{T<:Number}</i>(::<b>AbstractArray{T<:Number,2}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/operators.jl#L381\" target=\"_blank\">operators.jl:381</a><li> sin<i>{T<:Number}</i>(::<b>AbstractArray{T<:Number,N}</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/operators.jl#L383\" target=\"_blank\">operators.jl:383</a><li> sin<i>{T<:FixedSizeArrays.FixedArray{T,NDim,SIZE}}</i>(x::<b>T<:FixedSizeArrays.FixedArray{T,NDim,SIZE}</b>) at <a href=\"https://github.com/SimonDanisch/FixedSizeArrays.jl/tree/01bf5f5f1776111a5ca05ed88566ab90253d9e99/src/ops.jl#L55\" target=\"_blank\">/Users/ddohan/.julia/v0.4/FixedSizeArrays/src/ops.jl:55</a><li> sin(x::<b>SymPy.Sym</b>) at <a href=\"https://github.com/jverzani/SymPy.jl/tree/d2f08e9d35f1fa84cfb5dc9427a31a4b19d51996/src/math.jl#L22\" target=\"_blank\">/Users/ddohan/.julia/v0.4/SymPy/src/math.jl:22</a></ul>" | |
], | |
"text/plain": [ | |
"# 14 methods for generic function \"sin\":\n", | |
"sin(a::Complex{Float16}) at float16.jl:151\n", | |
"sin(z::Complex{T<:Real}) at complex.jl:548\n", | |
"sin(x::Float64) at math.jl:137\n", | |
"sin(x::Float32) at math.jl:138\n", | |
"sin(a::Float16) at float16.jl:150\n", | |
"sin(x::BigFloat) at mpfr.jl:610\n", | |
"sin(x::Real) at math.jl:139\n", | |
"sin{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) at sparse/sparsematrix.jl:648\n", | |
"sin(a::Array{SymPy.Sym,N}) at /Users/ddohan/.julia/v0.4/SymPy/src/math.jl:25\n", | |
"sin{T<:Number}(::AbstractArray{T<:Number,1}) at operators.jl:380\n", | |
"sin{T<:Number}(::AbstractArray{T<:Number,2}) at operators.jl:381\n", | |
"sin{T<:Number}(::AbstractArray{T<:Number,N}) at operators.jl:383\n", | |
"sin{T<:FixedSizeArrays.FixedArray{T,NDim,SIZE}}(x::T<:FixedSizeArrays.FixedArray{T,NDim,SIZE}) at /Users/ddohan/.julia/v0.4/FixedSizeArrays/src/ops.jl:55\n", | |
"sin(x::SymPy.Sym) at /Users/ddohan/.julia/v0.4/SymPy/src/math.jl:22" | |
] | |
}, | |
"execution_count": 40, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Notice that the sin on SymPy is just added as another dispatch option\n", | |
"methods(sin)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Witchcraft: defining Python classes IN JULIA" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"using PyCall" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"PyObject <class 'Generator'>" | |
] | |
}, | |
"execution_count": 42, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"@pydef type Generator\n", | |
" __init__(self, vals) = (self[:vals] = vals; self[:i] = 1)\n", | |
" next(self) = begin\n", | |
" i = self[:i]\n", | |
" self[:i] = max((i + 1) % length(self[:vals]), 1)\n", | |
" return self[:vals][i]\n", | |
" end\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"10-element Array{Any,1}:\n", | |
" 1\n", | |
" 2\n", | |
" 3\n", | |
" 4\n", | |
" 1\n", | |
" 2\n", | |
" 3\n", | |
" 4\n", | |
" 1\n", | |
" 2" | |
] | |
}, | |
"execution_count": 43, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"pyeval(\"[next(x) for i in range(0,10)]\", x=Generator([1,2,3,4,5]))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Short interlude over to [`go.jl`](https://github.com/dmrd/go.jl/blob/master/src/policy.jl)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Calling Julia from Python\n", | |
"```\n", | |
"from julia import Julia\n", | |
"jl = Julia()\n", | |
"func = jl.eval(\"\"\"\n", | |
" function f(n)\n", | |
" ...\n", | |
" end\n", | |
" \"\"\")\n", | |
"func(5)\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## C++: Cxx\n", | |
"[switch to Julia dev]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Tools for writing simple scripts\n", | |
"- Julia makes it easy to write simple data munging and scripts that interact with filesystem\n", | |
"\n", | |
"- at repl, ; goes to command line mode" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Cxx.ipynb\n", | |
"Intro to Julia.ipynb\n", | |
"images\n", | |
"julia5bak.ipynb\n", | |
"opencv.jl\n" | |
] | |
} | |
], | |
"source": [ | |
";ls" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 45, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Cxx.ipynb\n", | |
"Intro to Julia.ipynb\n", | |
"images\n", | |
"julia5bak.ipynb\n", | |
"opencv.jl\n" | |
] | |
} | |
], | |
"source": [ | |
"run(`ls`)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"images\n" | |
] | |
} | |
], | |
"source": [ | |
"run(pipeline(`ls`, `grep image`))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 47, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"\"hello\\n\"" | |
] | |
}, | |
"execution_count": 47, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"result = readall(`echo hello`)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 48, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"`rm -rf foo.aux foo.log foo.pdf bar.aux bar.log bar.pdf baz.aux baz.log baz.pdf qux.aux qux.log qux.pdf`" | |
] | |
}, | |
"execution_count": 48, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"`rm -rf $[\"foo\",\"bar\",\"baz\",\"qux\"].$[\"aux\",\"log\",\"pdf\"]`" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Designed for parallelism in mind" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 49, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"parallel_findpi (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 49, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# julia -p4 to launch with multiple workers\n", | |
"function findpi(n)\n", | |
" inside = 0\n", | |
" for i = 1:n\n", | |
" x, y = rand(2)\n", | |
" if (x^2 + y^2 <= 1.0)\n", | |
" inside += 1\n", | |
" end\n", | |
" end\n", | |
" 4.0 * inside / n\n", | |
"end\n", | |
"\n", | |
"function parallel_findpi(n)\n", | |
" inside = @parallel (+) for i = 1:n\n", | |
" x, y = rand(2)\n", | |
" x^2 + y^2 <= 1.0 ? 1 : 0\n", | |
" end\n", | |
" 4.0 * inside / n\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Performance\n", | |
"\n", | |
"## Benchmarks\n", | |
"- As with all benchmarks, read with caution, but gives the overall message: Julia can go fast\n", | |
"<img src=\"images/benchmarks.png\">" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 50, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"arraysum2 (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 50, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Type instability makes for slow code\n", | |
"# Dev tools exist to detect this\n", | |
"function arraysum1(x)\n", | |
" total = 0 # Here total is defined as an int\n", | |
" for i=1:length(x)\n", | |
" total += x[i]\n", | |
" end \n", | |
" total\n", | |
"end\n", | |
"\n", | |
"function arraysum2(x)\n", | |
" total = 0.0 # Here total is defined as a float\n", | |
" for i=1:length(x)\n", | |
" total += x[i]\n", | |
" end \n", | |
" total\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 51, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 0.761832 seconds (20.00 M allocations: 305.307 MB, 23.13% gc time)\n", | |
" 0.024545 seconds (1.91 k allocations: 96.148 KB)\n" | |
] | |
} | |
], | |
"source": [ | |
"arr = ones(10000000) # Ones creates floats\n", | |
"@time arraysum1(arr);\n", | |
"@time arraysum2(arr);" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Going down the ladder of abstraction\n", | |
"- Julia lets you dive down into what your code is *actually* doing" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 52, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"sq (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 52, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"\"Square the argument\"\n", | |
"sq(x) = x^2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 53, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"search: sq sqr sqf sqrt sqrtm square squeeze sqf_part sqf_norm sqf_list\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"Square the argument\n" | |
], | |
"text/markdown": [ | |
"Square the argument\n" | |
], | |
"text/plain": [ | |
"Square the argument\n" | |
] | |
}, | |
"execution_count": 53, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"?sq" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 54, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"\n", | |
"define i64 @julia_sq_23257(i64) {\n", | |
"top:\n", | |
" %1 = mul i64 %0, %0\n", | |
" ret i64 %1\n", | |
"}\n", | |
"\n", | |
"define double @julia_sq_23262(double) {\n", | |
"top:\n", | |
" %1 = fmul double %0, %0\n", | |
" ret double %1\n", | |
"}\n" | |
] | |
} | |
], | |
"source": [ | |
"# LLVM assembly\n", | |
"@code_llvm sq(5)\n", | |
"@code_llvm sq(5.0)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 55, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"\t.section\t__TEXT,__text,regular,pure_instructions\n", | |
"Filename: In[52]\n", | |
"Source line: 2\n", | |
"\tpushq\t%rbp\n", | |
"\tmovq\t%rsp, %rbp\n", | |
"Source line: 2\n", | |
"\timulq\t%rdi, %rdi\n", | |
"\tmovq\t%rdi, %rax\n", | |
"\tpopq\t%rbp\n", | |
"\tret\n", | |
"\t.section\t__TEXT,__text,regular,pure_instructions\n", | |
"Filename: In[52]\n", | |
"Source line: 2\n", | |
"\tpushq\t%rbp\n", | |
"\tmovq\t%rsp, %rbp\n", | |
"Source line: 2\n", | |
"\tmulsd\t%xmm0, %xmm0\n", | |
"\tpopq\t%rbp\n", | |
"\tret\n" | |
] | |
} | |
], | |
"source": [ | |
"# Native assembly\n", | |
"@code_native sq(5)\n", | |
"@code_native sq(5.0)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Julia is a Lisp with full macros\n", | |
"- Disclaimer: I am not a Lisper\n", | |
"- @macro syntax\n", | |
"<img src=\"images/macros.png\">" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 56, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Expr \n", | |
" head: Symbol call\n", | |
" args: Array(Any,(3,))\n", | |
" 1: Symbol +\n", | |
" 2: Int64 1\n", | |
" 3: Symbol b\n", | |
" typ: Any\n" | |
] | |
} | |
], | |
"source": [ | |
"dump(:(1 + b))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 57, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"+(x::<b>Number</b>, y::<b>Number</b>) at <a href=\"https://github.com/JuliaLang/julia/tree/a2f713dea5ac6320d8dcf2835ac4a37ea751af05/base/promotion.jl#L167\" target=\"_blank\">promotion.jl:167</a>" | |
], | |
"text/plain": [ | |
"+(x::Number, y::Number) at promotion.jl:167" | |
] | |
}, | |
"execution_count": 57, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Simple example: macro pulls apart expression to determine which method will be dispatched\n", | |
"@which 1 + 2.0" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 58, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 0.515242 seconds (36.40 k allocations: 1.604 MB)\n" | |
] | |
} | |
], | |
"source": [ | |
"@time rand(10000);" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 59, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
":(Base.code_native(sq,(Base.typesof)(5)))" | |
] | |
}, | |
"execution_count": 59, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"macroexpand(:(@code_native sq(5)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 60, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"quote # util.jl, line 153:\n", | |
" local #106#stats = Base.gc_num() # util.jl, line 154:\n", | |
" local #108#elapsedtime = Base.time_ns() # util.jl, line 155:\n", | |
" local #107#val = rand(100000) # util.jl, line 156:\n", | |
" #108#elapsedtime = Base.-(Base.time_ns(),#108#elapsedtime) # util.jl, line 157:\n", | |
" local #109#diff = Base.GC_Diff(Base.gc_num(),#106#stats) # util.jl, line 158:\n", | |
" Base.time_print(#108#elapsedtime,#109#diff.allocd,#109#diff.total_time,Base.gc_alloc_count(#109#diff)) # util.jl, line 160:\n", | |
" #107#val\n", | |
"end" | |
] | |
}, | |
"execution_count": 60, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"macroexpand(:(@time rand(100000)))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Neat example application: [flow.jl](https://github.com/MikeInnes/Flow.jl)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"## Generated Functions " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 61, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"foo (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 61, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Super simple example\n", | |
"# Generate a function body based on type of arguments\n", | |
"# Basically macros after type inference -> has type information\n", | |
"@generated function foo(x)\n", | |
" @show x\n", | |
" :(println(\"foo is \", x))\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 62, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"x = Int64\n", | |
"foo is 1\n" | |
] | |
} | |
], | |
"source": [ | |
"foo(1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 63, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"foo is 2\n" | |
] | |
} | |
], | |
"source": [ | |
"# Note that the function is cached\n", | |
"foo(2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 64, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"x = Float64\n", | |
"foo is 1.0\n" | |
] | |
} | |
], | |
"source": [ | |
"foo(1.0)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"[Generated functions](https://groups.google.com/forum/#!topic/julia-users/a9PwoRvn4CU):\n", | |
"- Macros are functions evaluated at parse time, given the symbolic expressions (ASTs) of the arguments and returning a transformed expression\n", | |
"- Generated functions are functions evaluated at compile time, given the types of the arguments and returning a symbolic expression\n", | |
"- Ordinary functions are functions evaluated at runtime, given the values of the arguments and returning a value.\n", | |
"\n", | |
"\"\n", | |
"Keno's C++ interface (https://github.com/Keno/Cxx.jl) relies on generated functions. In order to call C++ functions, you need to know the argument types, and you don't generally know types until compile time. By allowing the C++ call to be computed at compile time via generated functions, you pay no runtime overhead for invoking the enormous Clang machinery to figure out C++.\n", | |
"\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# What's not so good?\n", | |
"- Still a young language\n", | |
" - still making breaking changes\n", | |
"- community isn't nearly as large as python\n", | |
" - not as much of a problem because it is so easy to wrap existing code\n", | |
"- Devtools aren't there yet\n", | |
" - Just getting a proper debugger\n", | |
" - IDE support isn't great" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Julia 0.4.3", | |
"language": "julia", | |
"name": "julia-0.4" | |
}, | |
"language_info": { | |
"file_extension": ".jl", | |
"mimetype": "application/julia", | |
"name": "julia", | |
"version": "0.4.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment