{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"nbpresent": {
"id": "d8145165-8d8e-4c7d-8511-710cae0113ed"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 最新Juliaチュートリアル\n",
"\n",
"2017/08/22 @JuliaTokyo #7 (https://juliatokyo.connpass.com/event/62233/)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpresent": {
"id": "385e0a13-6529-48cc-8a68-5401cb5e11ed"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 今日の話\n",
"\n",
"概要\n",
"- Juliaとは?\n",
"- Juliaの基礎知識\n",
"- Juliaの実行モデル\n",
"- 今後の動向\n",
"\n",
"目的\n",
"- 構文や基本的な機能を理解する\n",
"- 実行の仕方を理解し、高速なプログラムが書けるようになる\n",
"- 最新の動向にキャッチアップする"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 自己紹介"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"https://github.com/bicycle1885"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpresent": {
"id": "c825d089-a85d-4f52-9b30-88f6e5f6ce3b"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Juliaとは?\n",
"\n",
"科学技術計算を目的として作られた動的プログラミング言語\n",
"\n",
"- 数値計算用の豊富な標準ライブラリ\n",
"- `for`ループが超速い\n",
"- 平易な構文・シンプルな言語機能\n",
"- CやFortranとの連携が容易\n",
"- オープンソース (MITライセンス)\n",
"\n",
"http://julialang.org\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Hello, PCA!"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pca (generic function with 1 method)"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function pca(X)\n",
" X̄ = X .- mean(X, 1)\n",
" U, Σ, V = svd(X̄)\n",
" return X̄ * V\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"150×4 Array{Float64,2}:\n",
" 5.1 3.5 1.4 0.2\n",
" 4.9 3.0 1.4 0.2\n",
" 4.7 3.2 1.3 0.2\n",
" 4.6 3.1 1.5 0.2\n",
" 5.0 3.6 1.4 0.2\n",
" 5.4 3.9 1.7 0.4\n",
" 4.6 3.4 1.4 0.3\n",
" 5.0 3.4 1.5 0.2\n",
" 4.4 2.9 1.4 0.2\n",
" 4.9 3.1 1.5 0.1\n",
" 5.4 3.7 1.5 0.2\n",
" 4.8 3.4 1.6 0.2\n",
" 4.8 3.0 1.4 0.1\n",
" ⋮ \n",
" 6.0 3.0 4.8 1.8\n",
" 6.9 3.1 5.4 2.1\n",
" 6.7 3.1 5.6 2.4\n",
" 6.9 3.1 5.1 2.3\n",
" 5.8 2.7 5.1 1.9\n",
" 6.8 3.2 5.9 2.3\n",
" 6.7 3.3 5.7 2.5\n",
" 6.7 3.0 5.2 2.3\n",
" 6.3 2.5 5.0 1.9\n",
" 6.5 3.0 5.2 2.0\n",
" 6.2 3.4 5.4 2.3\n",
" 5.9 3.0 5.1 1.8"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iris = readcsv(\"iris.csv\", header=true)[1]\n",
"X = convert(Matrix{Float64}, iris[:,1:4])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"150×4 Array{Float64,2}:\n",
" -2.68413 -0.319397 0.0279148 0.00226244\n",
" -2.71414 0.177001 0.210464 0.0990266 \n",
" -2.88899 0.144949 -0.0179003 0.0199684 \n",
" -2.74534 0.318299 -0.0315594 -0.0755758 \n",
" -2.72872 -0.326755 -0.0900792 -0.0612586 \n",
" -2.28086 -0.74133 -0.168678 -0.0242009 \n",
" -2.82054 0.0894614 -0.257892 -0.0481431 \n",
" -2.62614 -0.163385 0.0218793 -0.0452979 \n",
" -2.88638 0.578312 -0.0207596 -0.0267447 \n",
" -2.67276 0.113774 0.197633 -0.0562954 \n",
" -2.50695 -0.645069 0.075318 -0.0150199 \n",
" -2.61276 -0.0147299 -0.10215 -0.156379 \n",
" -2.78611 0.235112 0.206844 -0.00788791\n",
" ⋮ \n",
" 1.16933 0.16499 -0.281836 0.0204618 \n",
" 2.10761 -0.372288 -0.0272911 0.210622 \n",
" 2.31415 -0.183651 -0.322694 0.277654 \n",
" 1.92227 -0.409203 -0.113587 0.505305 \n",
" 1.41524 0.574916 -0.296323 -0.0153047 \n",
" 2.56301 -0.277863 -0.29257 0.0579127 \n",
" 2.41875 -0.304798 -0.504483 0.241091 \n",
" 1.94411 -0.187532 -0.177825 0.426196 \n",
" 1.52717 0.375317 0.121898 0.254367 \n",
" 1.76435 -0.0788589 -0.130482 0.137001 \n",
" 1.90094 -0.116628 -0.723252 0.0445953 \n",
" 1.39019 0.282661 -0.36291 -0.155039 "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_pca = pca(X)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"PyPlot.Figure(PyObject )"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"using PyPlot\n",
"species = iris[:,5]\n",
"cmap = Dict(s => \"C$(i-1)\" for (i, s) in enumerate(unique(species)))\n",
"scatter(X_pca[:,1], X_pca[:,2], c=getindex.(cmap, species));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 数値計算への強さ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**多次元配列**を標準搭載\n",
"- 任意次元の配列\n",
"- ブロードキャスト\n",
"- 平均・分散・中央値など統計量の計算関数\n",
"\n",
"**高速な数値計算ライブラリ**を標準搭載\n",
"- OpenBLAS: 各アーキテクチャに最適化された行列計算ライブラリ\n",
"- LAPACK: 行列分解など線型方程式を扱うライブラリ\n",
"- DSFMT: 高速なメルセンヌ・ツイスター擬似乱生成器"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"srand(1234);"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Float64,1}:\n",
" 0.590845\n",
" 0.766797\n",
" 0.566237"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rand(3) # 1次元配列"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Float64,2}:\n",
" 0.460085 0.200586 0.579672 \n",
" 0.794026 0.298614 0.648882 \n",
" 0.854147 0.246837 0.0109059"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rand(3, 3) # 2次元配列"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3×3 Array{Float64,3}:\n",
"[:, :, 1] =\n",
" 0.066423 0.112486 0.0566425\n",
" 0.956753 0.276021 0.842714 \n",
" 0.646691 0.651664 0.950498 \n",
"\n",
"[:, :, 2] =\n",
" 0.96467 0.82116 0.314926\n",
" 0.945775 0.0341601 0.12781 \n",
" 0.789904 0.0945445 0.374187\n",
"\n",
"[:, :, 3] =\n",
" 0.931115 0.0118196 0.732 \n",
" 0.438939 0.0460428 0.299058\n",
" 0.246862 0.496169 0.449182"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rand(3, 3, 3) # 3次元配列"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4×3 Array{Float64,2}:\n",
" 0.9481 1.22519 1.05156 \n",
" 1.40751 1.71371 0.97805 \n",
" 0.561272 0.733818 0.669705\n",
" 0.0696456 0.112251 0.200629"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = randn(4, 2)\n",
"B = randn(2, 3)\n",
"A * B # 行列積"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rank(A * B)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"U, Σ, V = svd(A * B); # 特異値分解"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4×3 Array{Float64,2}:\n",
" -0.571725 0.532279 0.619488\n",
" -0.740511 -0.643106 -0.146947\n",
" -0.347219 0.4311 -0.621254\n",
" -0.0649046 0.342412 -0.45682 "
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"U"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Float64,1}:\n",
" 3.26033 \n",
" 0.332009 \n",
" 2.64666e-16"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Σ"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Float64,2}:\n",
" -0.547103 -0.405747 0.732153\n",
" -0.684464 -0.286656 -0.670326\n",
" -0.481859 0.86787 0.120889"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"V"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"欧米を中心に、数値計算の授業でもJuliaが使われている: https://julialang.org/teaching/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## forループも速い"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ユーザーの声\n",
"\n",
"- https://twitter.com/sammy_suyama/status/899271832234151937\n",
"- https://twitter.com/genkuroki/status/899171709839745024\n",
"- https://twitter.com/tkf/status/804218261248176128\n",
"- https://twitter.com/antiplastics/status/874982350509047808\n",
"- https://twitter.com/bicycle1885/status/879493129933438976\n",
"\n",
"※ 個人の感想です"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"add (generic function with 1 method)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function add(x, y)\n",
" output = similar(x)\n",
" @inbounds for i in 1:endof(x)\n",
" output[i] = x[i] + y[i]\n",
" end\n",
" return output\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"x = randn(100_000);\n",
"y = randn(100_000);"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 0.008612 seconds (2 allocations: 781.328 KiB, 92.76% gc time)\n",
" 0.000611 seconds (2 allocations: 781.328 KiB)\n",
" 0.000707 seconds (2 allocations: 781.328 KiB)\n",
" 0.000664 seconds (2 allocations: 781.328 KiB)\n",
" 0.000565 seconds (2 allocations: 781.328 KiB)\n"
]
}
],
"source": [
"x + y\n",
"for _ in 1:5\n",
" @time x + y\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 0.000556 seconds (2 allocations: 781.328 KiB)\n",
" 0.000637 seconds (2 allocations: 781.328 KiB)\n",
" 0.000612 seconds (2 allocations: 781.328 KiB)\n",
" 0.000671 seconds (2 allocations: 781.328 KiB)\n",
" 0.000528 seconds (2 allocations: 781.328 KiB)\n"
]
}
],
"source": [
"add(x, y)\n",
"for _ in 1:5\n",
" @time add(x, y)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"using PyCall"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"v\"3.5.2\""
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"PyCall.pyversion"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"py\"\"\"\n",
"import numpy as np\n",
"\n",
"def add(x, y):\n",
" output = np.empty(x.shape)\n",
" for i in range(len(x)):\n",
" output[i] = x[i] + y[i]\n",
" return output\n",
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 0.047117 seconds (2.01 k allocations: 115.593 KiB)\n"
]
}
],
"source": [
"@time py\"add($(x), $(y))\"o;"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"using BenchmarkTools"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Julia Version 0.6.0\n",
"Commit 903644385b* (2017-06-19 13:05 UTC)\n",
"Platform Info:\n",
" OS: macOS (x86_64-apple-darwin16.6.0)\n",
" CPU: Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz\n",
" WORD_SIZE: 64\n",
" BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)\n",
" LAPACK: libopenblas64_\n",
" LIBM: libopenlibm\n",
" LLVM: libLLVM-3.9.1 (ORCJIT, skylake)\n"
]
}
],
"source": [
"versioninfo()"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 781.33 KiB\n",
" allocs estimate: 2\n",
" --------------\n",
" minimum time: 71.093 μs (0.00% GC)\n",
" median time: 126.816 μs (0.00% GC)\n",
" mean time: 380.584 μs (21.48% GC)\n",
" maximum time: 16.920 ms (0.00% GC)\n",
" --------------\n",
" samples: 10000\n",
" evals/sample: 1"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b1 = @benchmark x + y"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.4066082455375352e9"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# FLOPS\n",
"100_000 / (minimum(b1).time / 10^9)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 781.33 KiB\n",
" allocs estimate: 2\n",
" --------------\n",
" minimum time: 70.281 μs (0.00% GC)\n",
" median time: 99.873 μs (0.00% GC)\n",
" mean time: 318.488 μs (20.56% GC)\n",
" maximum time: 7.014 ms (86.54% GC)\n",
" --------------\n",
" samples: 10000\n",
" evals/sample: 1"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b2 = @benchmark add(x, y)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.4228596633514037e9"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# FLOPS\n",
"100_000 / (minimum(b2).time / 10^9)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.TrialJudgement: \n",
" time: +1.16% => invariant (5.00% tolerance)\n",
" memory: +0.00% => invariant (1.00% tolerance)"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"judge(minimum(b1), minimum(b2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 速さの秘密\n",
"\n",
"主に2つの要素\n",
"- **型推論**による実行時の曖昧性の排除\n",
"- **LLVM**によるネイティブコードへの変換\n",
"\n",
"これらにより他の動的言語では実現が難しいほどの最適化ができる"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`add(x, y)`の型推論の結果"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin \n",
" $(Expr(:inbounds, false))\n",
" # meta: location array.jl similar 189\n",
" SSAValue(3) = (Base.arraysize)(x, 1)::Int64\n",
" # meta: pop location\n",
" $(Expr(:inbounds, :pop))\n",
" output = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float64,1}, svec(Any, Int64), Array{Float64,1}, 0, SSAValue(3), 0)) # line 3:\n",
" $(Expr(:inbounds, true))\n",
" $(Expr(:inbounds, false))\n",
" # meta: location abstractarray.jl endof 134\n",
" $(Expr(:inbounds, false))\n",
" # meta: location abstractarray.jl linearindices 99\n",
" # meta: location abstractarray.jl indices1 71\n",
" # meta: location abstractarray.jl indices 64\n",
" SSAValue(7) = (Base.arraysize)(x, 1)::Int64\n",
" # meta: pop location\n",
" # meta: pop location\n",
" # meta: pop location\n",
" $(Expr(:inbounds, :pop))\n",
" # meta: pop location\n",
" $(Expr(:inbounds, :pop))\n",
" SSAValue(8) = (Base.select_value)((Base.slt_int)(SSAValue(7), 0)::Bool, 0, SSAValue(7))::Int64\n",
" SSAValue(9) = (Base.select_value)((Base.sle_int)(1, SSAValue(8))::Bool, SSAValue(8), (Base.sub_int)(1, 1)::Int64)::Int64\n",
" #temp# = 1\n",
" 25: \n",
" unless (Base.not_int)((#temp# === (Base.add_int)(SSAValue(9), 1)::Int64)::Bool)::Bool goto 36\n",
" SSAValue(10) = #temp#\n",
" SSAValue(11) = (Base.add_int)(#temp#, 1)::Int64\n",
" i = SSAValue(10)\n",
" #temp# = SSAValue(11) # line 4:\n",
" SSAValue(2) = (Base.add_float)((Base.arrayref)(x, i)::Float64, (Base.arrayref)(y, i)::Float64)::Float64\n",
" (Base.arrayset)(output, SSAValue(2), i)::Array{Float64,1}\n",
" 34: \n",
" goto 25\n",
" 36: \n",
" $(Expr(:inbounds, :pop)) # line 6:\n",
" return output\n",
" end))=>Array{Float64,1}"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed add(x, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"LLVMによるネイティブコードへの変換"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\t.section\t__TEXT,__text,regular,pure_instructions\n",
"Filename: In[15]\n",
"\tpushq\t%rbp\n",
"\tmovq\t%rsp, %rbp\n",
"\tpushq\t%r15\n",
"\tpushq\t%r14\n",
"\tpushq\t%rbx\n",
"\tsubq\t$40, %rsp\n",
"\tmovq\t%rsi, %r15\n",
"\tmovq\t%rdi, %rbx\n",
"\tmovabsq\t$jl_get_ptls_states_fast, %rax\n",
"\tcallq\t*%rax\n",
"\tmovq\t%rax, %r14\n",
"\tvxorpd\t%xmm0, %xmm0, %xmm0\n",
"\tvmovupd\t%xmm0, -40(%rbp)\n",
"\tmovq\t$4, -56(%rbp)\n",
"\tmovq\t(%r14), %rax\n",
"\tmovq\t%rax, -48(%rbp)\n",
"\tleaq\t-56(%rbp), %rax\n",
"\tmovq\t%rax, (%r14)\n",
"Source line: 189\n",
"\tmovq\t24(%rbx), %rsi\n",
"Source line: 2\n",
"\tmovabsq\t$jl_alloc_array_1d, %rax\n",
"\tleaq\t99153040(%rax), %rdi\n",
"\tcallq\t*%rax\n",
"\tmovq\t%rax, -40(%rbp)\n",
"Source line: 64\n",
"\tmovq\t24(%rbx), %rcx\n",
"Source line: 3\n",
"\ttestq\t%rcx, %rcx\n",
"\tjle\tL354\n",
"Source line: 4\n",
"\tmovq\t(%rbx), %r9\n",
"\tmovq\t(%r15), %r10\n",
"\tmovq\t(%rax), %r11\n",
"\tmovl\t$1, %r15d\n",
"Source line: 3\n",
"\tcmpq\t$8, %rcx\n",
"\tjb\tL290\n",
"\tmovq\t%rcx, %r8\n",
"\tmovl\t$1, %r15d\n",
"\tandq\t$-8, %r8\n",
"\tje\tL290\n",
"\tleaq\t(%r11,%rcx,8), %rsi\n",
"\tleaq\t(%r9,%rcx,8), %rdx\n",
"\tleaq\t(%r10,%rcx,8), %rdi\n",
"\tcmpq\t%rdx, %r11\n",
"\tsbbb\t%dl, %dl\n",
"\tcmpq\t%rsi, %r9\n",
"\tsbbb\t%bl, %bl\n",
"\tandb\t%dl, %bl\n",
"\tcmpq\t%rdi, %r11\n",
"\tsbbb\t%dl, %dl\n",
"\tcmpq\t%rsi, %r10\n",
"\tsbbb\t%sil, %sil\n",
"\tmovl\t$1, %r15d\n",
"\ttestb\t$1, %bl\n",
"\tjne\tL290\n",
"\tandb\t%sil, %dl\n",
"\tandb\t$1, %dl\n",
"\tjne\tL290\n",
"\tmovq\t%r8, %r15\n",
"\torq\t$1, %r15\n",
"\tleaq\t32(%r9), %rdx\n",
"\tleaq\t32(%r10), %rsi\n",
"\tleaq\t32(%r11), %rdi\n",
"\tmovq\t%r8, %rbx\n",
"\tnopw\t%cs:(%rax,%rax)\n",
"Source line: 4\n",
"L240:\n",
"\tvmovupd\t-32(%rdx), %ymm0\n",
"\tvmovupd\t(%rdx), %ymm1\n",
"\tvaddpd\t-32(%rsi), %ymm0, %ymm0\n",
"\tvaddpd\t(%rsi), %ymm1, %ymm1\n",
"\tvmovupd\t%ymm0, -32(%rdi)\n",
"\tvmovupd\t%ymm1, (%rdi)\n",
"Source line: 3\n",
"\taddq\t$64, %rdx\n",
"\taddq\t$64, %rsi\n",
"\taddq\t$64, %rdi\n",
"\taddq\t$-8, %rbx\n",
"\tjne\tL240\n",
"\tcmpq\t%r8, %rcx\n",
"\tje\tL350\n",
"L290:\n",
"\taddq\t$1, %rcx\n",
"\tsubq\t%r15, %rcx\n",
"\tleaq\t-8(%r11,%r15,8), %rdx\n",
"\tleaq\t-8(%r10,%r15,8), %rsi\n",
"\tleaq\t-8(%r9,%r15,8), %rdi\n",
"\tnopl\t(%rax,%rax)\n",
"Source line: 4\n",
"L320:\n",
"\tvmovsd\t(%rdi), %xmm0 ## xmm0 = mem[0],zero\n",
"\tvaddsd\t(%rsi), %xmm0, %xmm0\n",
"\tvmovsd\t%xmm0, (%rdx)\n",
"Source line: 3\n",
"\taddq\t$8, %rdx\n",
"\taddq\t$8, %rsi\n",
"\taddq\t$8, %rdi\n",
"\taddq\t$-1, %rcx\n",
"\tjne\tL320\n",
"Source line: 4\n",
"L350:\n",
"\tmovq\t%rax, -32(%rbp)\n",
"Source line: 6\n",
"L354:\n",
"\tmovq\t-48(%rbp), %rcx\n",
"\tmovq\t%rcx, (%r14)\n",
"\taddq\t$40, %rsp\n",
"\tpopq\t%rbx\n",
"\tpopq\t%r14\n",
"\tpopq\t%r15\n",
"\tpopq\t%rbp\n",
"\tvzeroupper\n",
"\tretq\n",
"\tnopw\t(%rax,%rax)\n"
]
}
],
"source": [
"@code_native add(x, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ネイティブコードはCPUで直接実行されるので、仮想マシン(VM)を使う他のインタプリター方式の言語より高速"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Juliaの基礎知識"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"もうちょっと包括的な日本語のチュートリアル➥ https://github.com/bicycle1885/Julia-Tutorial"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 基本構文 - 分岐"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"zero!\n"
]
}
],
"source": [
"x = rand([-1, 0, 1])\n",
"\n",
"if x > 0\n",
" println(\"positive!\")\n",
"elseif x == 0\n",
" println(\"zero!\")\n",
"else\n",
" println(\"negative!\")\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 基本構文 - 反復"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n",
"2\n",
"3\n",
"4\n",
"5\n",
"6\n",
"7\n",
"8\n",
"9\n",
"10\n"
]
}
],
"source": [
"for i in 1:10\n",
" println(i)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"r = 0.824963896731119\n",
"r = 0.3864837619109138\n",
"r = 0.19716180707125286\n",
"r = 0.4707863823067948\n",
"r = 0.9122340342619175\n",
"r = 0.27714398262365547\n",
"r = 0.40275437809947934\n",
"r = 0.12027556668360484\n",
"r = 0.09447130478733246\n",
"r = 0.24197683192547736\n",
"r = 0.8619030597650075\n",
"r = 0.5945882942644753\n",
"r = 0.49438472096360275\n",
"r = 0.49150286529392995\n",
"r = 0.39888971732793155\n",
"r = 0.04482709506506044\n"
]
}
],
"source": [
"while true\n",
" r = rand()\n",
" @show r\n",
" if r < 0.05\n",
" break\n",
" end\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 基本構文 - 関数定義"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"hello (generic function with 1 method)"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# functioを使う関数定義\n",
"function hello(name)\n",
" return \"hello, $(name)!\"\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"hello (generic function with 1 method)"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 1行関数定義\n",
"hello(name) = \"hello, $(name)!!\""
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"hello (generic function with 2 methods)"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 引数の型制約付き\n",
"function hello(name::AbstractString)\n",
" return \"hello, $(name)!!!\"\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"hello (generic function with 2 methods)"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 引数と返り値の型制約付き\n",
"function hello(name::AbstractString)::String\n",
" return \"hello, $(name)!!!!\"\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Juliaの型"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Void"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# nothingの型\n",
"Void"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Void"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(nothing)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bool"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 真偽型\n",
"Bool"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bool"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(true)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Int8, Int16, Int32, Int64, Int128)"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 符号付き整数\n",
"Int8, Int16, Int32, Int64, Int128"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Int64"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(1)"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(UInt8, UInt16, UInt32, UInt64, UInt128)"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 符号無し整数\n",
"UInt8, UInt16, UInt32, UInt64, UInt128"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"UInt64"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(0x0000000000000001)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# エイリアス\n",
"Int == Int64"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# エイリアス\n",
"UInt == UInt64"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Float16, Float32, Float64)"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 浮動小数点数\n",
"Float16, Float32, Float64"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Float64"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(1.0)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Char"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 文字\n",
"Char"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Char"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof('a')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"リテラルによる型の違い"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Int64"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(1)"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"UInt8"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(0x01)"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"UInt16"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(0x0001)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Float64"
]
},
"execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(1.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"文字列"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"String"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"String"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"abracadabra\""
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\"abracadabra\""
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"アブラカダブラ\""
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\"アブラカダブラ\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"配列"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Array"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 1\n",
" 2\n",
" 3"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 1次元配列 (ベクトルとも言う)\n",
"[1, 2, 3]"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2×3 Array{Int64,2}:\n",
" 1 2 3\n",
" 4 5 6"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 2次元配列 (行列とも言う)\n",
"[1 2 3\n",
" 4 5 6]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"JuliaにPythonでいう`list`型はないが、1次元配列がその代わり"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"集合"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Set"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Set"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Set([2, 3, 1])"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Set([1, 2, 3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"辞書"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Dict"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dict"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Dict{String,Int64} with 2 entries:\n",
" \"two\" => 2\n",
" \"one\" => 1"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dict(\"one\" => 1, \"two\" => 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Nullable`型"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Nullable"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Nullable"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Nullable{Int64}(1)"
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Nullable(1)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Nullable{Int64}()"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Nullable{Int64}()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 抽象型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Int64`など具体型をまとめる型"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Int64"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Int"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Signed"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(Int)"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Integer"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(supertype(Int))"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Real"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(supertype(supertype(Int)))"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Number"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(supertype(supertype(supertype(Int))))"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Any"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(supertype(supertype(supertype(supertype(Int)))))"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Any"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"supertype(supertype(supertype(supertype(supertype(supertype(Int))))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"抽象型`AbstractMatrix`のサブタイプ"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"21-element Array{Union{DataType, UnionAll},1}:\n",
" AbstractSparseArray{Tv,Ti,2} where Ti where Tv \n",
" Base.LinAlg.AbstractTriangular \n",
" Base.LinAlg.HessenbergQ \n",
" Base.LinAlg.LQPackedQ \n",
" Base.LinAlg.QRCompactWYQ \n",
" Base.LinAlg.QRPackedQ \n",
" Base.LinAlg.SVDOperator \n",
" Base.ReshapedArray{T,2,P,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where P<:AbstractArray where T\n",
" Base.SparseArrays.CHOLMOD.FactorComponent \n",
" Bidiagonal \n",
" ConjArray{T,2,A} where A<:AbstractArray where T \n",
" DenseArray{T,2} where T \n",
" Diagonal \n",
" Hermitian \n",
" PermutedDimsArray{T,2,perm,iperm,AA} where AA<:AbstractArray where iperm where perm where T \n",
" PyCall.PyArray{T,2} where T \n",
" RowVector \n",
" SubArray{T,2,P,I,L} where L where I where P where T \n",
" SymTridiagonal \n",
" Symmetric \n",
" Tridiagonal "
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"subtypes(AbstractMatrix)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## パラメトリック型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"型パラメーターを取る型"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array"
]
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Array"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array{Int64,N} where N"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Array{Int}"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array{Int64,1}"
]
},
"execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Array{Int,1}"
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array{Int64,2}"
]
},
"execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Array{Int,2}"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array{Int64,1}"
]
},
"execution_count": 82,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof([1,2,3])"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Array{Int64,2}"
]
},
"execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof([1 2 3; 4 5 6])"
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Dict{String,Int64} with 2 entries:\n",
" \"two\" => 2\n",
" \"one\" => 1"
]
},
"execution_count": 84,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = Dict(\"one\" => 1, \"two\" => 2)"
]
},
{
"cell_type": "code",
"execution_count": 85,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Dict{String,Int64}"
]
},
"execution_count": 85,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"typeof(d)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 型定義"
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"struct User\n",
" name::String\n",
" registerdate::Date\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"User(\"Jeff Bezanson\", 2010-03-04)"
]
},
"execution_count": 87,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jeff = User(\"Jeff Bezanson\", Date(2010, 3, 4))"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"Jeff Bezanson\""
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jeff.name"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2010-03-04"
]
},
"execution_count": 89,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jeff.registerdate"
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mtype User is immutable\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mtype User is immutable\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"jeff.name = \"Stefan Karpinski\""
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"mutable struct MutableUser\n",
" name::String\n",
" registerdate::Date\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"MutableUser(\"Viral Shah\", 2013-10-02)"
]
},
"execution_count": 92,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"viral = MutableUser(\"Viral Shah\", Date(2013, 10, 2))"
]
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"Viral Shah\""
]
},
"execution_count": 93,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"viral.name"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"Alan Edelman\""
]
},
"execution_count": 94,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"viral.name = \"Alan Edelman\""
]
},
{
"cell_type": "code",
"execution_count": 95,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"MutableUser(\"Alan Edelman\", 2013-10-02)"
]
},
"execution_count": 95,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"viral"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 多重ディスパッチ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"関数`+`には180を超えるメソッドが定義されている"
]
},
{
"cell_type": "code",
"execution_count": 96,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"+ (generic function with 185 methods)"
]
},
"execution_count": 96,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"+"
]
},
{
"cell_type": "code",
"execution_count": 97,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"185 methods for generic function +:- +(x::Bool, z::Complex{Bool}) at complex.jl:232
- +(x::Bool, y::Bool) at bool.jl:89
- +(x::Bool) at bool.jl:86
- +{T<:AbstractFloat}(x::Bool, y::T) at bool.jl:96
- +(x::Bool, z::Complex) at complex.jl:239
- +(a::Float16, b::Float16) at float.jl:372
- +(x::Float32, y::Float32) at float.jl:374
- +(x::Float64, y::Float64) at float.jl:375
- +(z::Complex{Bool}, x::Bool) at complex.jl:233
- +(z::Complex{Bool}, x::Real) at complex.jl:247
- +(x::Char, y::Integer) at char.jl:40
- +(c::BigInt, x::BigFloat) at mpfr.jl:312
- +(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) at gmp.jl:334
- +(a::BigInt, b::BigInt, c::BigInt, d::BigInt) at gmp.jl:327
- +(a::BigInt, b::BigInt, c::BigInt) at gmp.jl:321
- +(x::BigInt, y::BigInt) at gmp.jl:289
- +(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) at gmp.jl:346
- +(x::BigInt, c::Union{Int16, Int32, Int64, Int8}) at gmp.jl:362
- +(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat) at mpfr.jl:460
- +(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat) at mpfr.jl:453
- +(a::BigFloat, b::BigFloat, c::BigFloat) at mpfr.jl:447
- +(x::BigFloat, c::BigInt) at mpfr.jl:308
- +(x::BigFloat, y::BigFloat) at mpfr.jl:277
- +(x::BigFloat, c::Union{UInt16, UInt32, UInt64, UInt8}) at mpfr.jl:284
- +(x::BigFloat, c::Union{Int16, Int32, Int64, Int8}) at mpfr.jl:292
- +(x::BigFloat, c::Union{Float16, Float32, Float64}) at mpfr.jl:300
- +(B::BitArray{2}, J::UniformScaling) at linalg/uniformscaling.jl:59
- +(a::Base.Pkg.Resolve.VersionWeights.VWPreBuildItem, b::Base.Pkg.Resolve.VersionWeights.VWPreBuildItem) at pkg/resolve/versionweight.jl:87
- +(a::Base.Pkg.Resolve.VersionWeights.VWPreBuild, b::Base.Pkg.Resolve.VersionWeights.VWPreBuild) at pkg/resolve/versionweight.jl:135
- +(a::Base.Pkg.Resolve.VersionWeights.VersionWeight, b::Base.Pkg.Resolve.VersionWeights.VersionWeight) at pkg/resolve/versionweight.jl:197
- +(a::Base.Pkg.Resolve.MaxSum.FieldValues.FieldValue, b::Base.Pkg.Resolve.MaxSum.FieldValues.FieldValue) at pkg/resolve/fieldvalue.jl:44
- +(x::Base.Dates.CompoundPeriod, y::Base.Dates.CompoundPeriod) at dates/periods.jl:349
- +(x::Base.Dates.CompoundPeriod, y::Base.Dates.Period) at dates/periods.jl:347
- +(x::Base.Dates.CompoundPeriod, y::Base.Dates.TimeType) at dates/periods.jl:387
- +(x::Date, y::Base.Dates.Day) at dates/arithmetic.jl:77
- +(x::Date, y::Base.Dates.Week) at dates/arithmetic.jl:75
- +(dt::Date, z::Base.Dates.Month) at dates/arithmetic.jl:58
- +(dt::Date, y::Base.Dates.Year) at dates/arithmetic.jl:32
- +(dt::Date, t::Base.Dates.Time) at dates/arithmetic.jl:20
- +(t::Base.Dates.Time, dt::Date) at dates/arithmetic.jl:24
- +(x::Base.Dates.Time, y::Base.Dates.TimePeriod) at dates/arithmetic.jl:81
- +(dt::DateTime, z::Base.Dates.Month) at dates/arithmetic.jl:52
- +(dt::DateTime, y::Base.Dates.Year) at dates/arithmetic.jl:28
- +(x::DateTime, y::Base.Dates.Period) at dates/arithmetic.jl:79
- +(a::PyCall.PyObject) at /Users/kenta/.julia/v0.6/PyCall/src/pyoperators.jl:36
- +(a::PyCall.PyObject, b) at /Users/kenta/.julia/v0.6/PyCall/src/pyoperators.jl:11
- +(y::AbstractFloat, x::Bool) at bool.jl:98
- +{T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}}(x::T, y::T) at int.jl:32
- +(x::Integer, y::Ptr) at pointer.jl:128
- +(z::Complex, w::Complex) at complex.jl:221
- +(z::Complex, x::Bool) at complex.jl:240
- +(x::Real, z::Complex{Bool}) at complex.jl:246
- +(x::Real, z::Complex) at complex.jl:258
- +(z::Complex, x::Real) at complex.jl:259
- +(x::Rational, y::Rational) at rational.jl:245
- +(x::Integer, y::Char) at char.jl:41
- +(i::Integer, index::CartesianIndex) at multidimensional.jl:79
- +(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigInt) at gmp.jl:350
- +(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) at gmp.jl:363
- +(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigFloat) at mpfr.jl:288
- +(c::Union{Int16, Int32, Int64, Int8}, x::BigFloat) at mpfr.jl:296
- +(c::Union{Float16, Float32, Float64}, x::BigFloat) at mpfr.jl:304
- +(x::Irrational, y::Irrational) at irrationals.jl:109
- +(x::Real, r::Base.Use_StepRangeLen_Instead) at deprecated.jl:1223
- +{T, f}(x::FixedPointNumbers.Fixed{T,f}, y::FixedPointNumbers.Fixed{T,f}) at /Users/kenta/.julia/v0.6/FixedPointNumbers/src/fixed.jl:30
- +{T, f}(x::FixedPointNumbers.Normed{T,f}, y::FixedPointNumbers.Normed{T,f}) at /Users/kenta/.julia/v0.6/FixedPointNumbers/src/normed.jl:81
- +(x::Number) at operators.jl:399
- +{T<:Number}(x::T, y::T) at promotion.jl:335
- +(x::Number, y::Number) at promotion.jl:249
- +(x::Real, r::AbstractUnitRange) at range.jl:721
- +(x::Number, r::AbstractUnitRange) at range.jl:723
- +(x::Number, r::StepRangeLen) at range.jl:726
- +(x::Number, r::LinSpace) at range.jl:730
- +(x::Number, r::Range) at range.jl:724
- +(r::Range, x::Number) at range.jl:732
- +(r1::OrdinalRange, r2::OrdinalRange) at range.jl:882
- +{T}(r1::LinSpace{T}, r2::LinSpace{T}) at range.jl:889
- +{R<:Base.TwicePrecision, T}(r1::StepRangeLen{T,R,S} where S, r2::StepRangeLen{T,R,S} where S) at twiceprecision.jl:300
- +{T, S}(r1::StepRangeLen{T,S,S} where S, r2::StepRangeLen{T,S,S} where S) at range.jl:905
- +(r1::Union{LinSpace, OrdinalRange, StepRangeLen}, r2::Union{LinSpace, OrdinalRange, StepRangeLen}) at range.jl:896
- +(x::Base.TwicePrecision, y::Number) at twiceprecision.jl:454
- +(x::Number, y::Base.TwicePrecision) at twiceprecision.jl:457
- +{T}(x::Base.TwicePrecision{T}, y::Base.TwicePrecision{T}) at twiceprecision.jl:460
- +(x::Base.TwicePrecision, y::Base.TwicePrecision) at twiceprecision.jl:464
- +(x::Ptr, y::Integer) at pointer.jl:126
- +(A::BitArray, B::BitArray) at bitarray.jl:1176
- +(A::SymTridiagonal, B::SymTridiagonal) at linalg/tridiag.jl:128
- +(A::Tridiagonal, B::Tridiagonal) at linalg/tridiag.jl:624
- +(A::UpperTriangular, B::UpperTriangular) at linalg/triangular.jl:374
- +(A::LowerTriangular, B::LowerTriangular) at linalg/triangular.jl:375
- +(A::UpperTriangular, B::Base.LinAlg.UnitUpperTriangular) at linalg/triangular.jl:376
- +(A::LowerTriangular, B::Base.LinAlg.UnitLowerTriangular) at linalg/triangular.jl:377
- +(A::Base.LinAlg.UnitUpperTriangular, B::UpperTriangular) at linalg/triangular.jl:378
- +(A::Base.LinAlg.UnitLowerTriangular, B::LowerTriangular) at linalg/triangular.jl:379
- +(A::Base.LinAlg.UnitUpperTriangular, B::Base.LinAlg.UnitUpperTriangular) at linalg/triangular.jl:380
- +(A::Base.LinAlg.UnitLowerTriangular, B::Base.LinAlg.UnitLowerTriangular) at linalg/triangular.jl:381
- +(A::Base.LinAlg.AbstractTriangular, B::Base.LinAlg.AbstractTriangular) at linalg/triangular.jl:382
- +(A::Symmetric, x::Bool) at linalg/symmetric.jl:272
- +(A::Symmetric, x::Number) at linalg/symmetric.jl:274
- +(A::Hermitian, x::Bool) at linalg/symmetric.jl:272
- +(A::Hermitian, x::Real) at linalg/symmetric.jl:274
- +(Da::Diagonal, Db::Diagonal) at linalg/diagonal.jl:140
- +(A::Bidiagonal, B::Bidiagonal) at linalg/bidiag.jl:330
- +(UL::UpperTriangular, J::UniformScaling) at linalg/uniformscaling.jl:72
- +(UL::Base.LinAlg.UnitUpperTriangular, J::UniformScaling) at linalg/uniformscaling.jl:75
- +(UL::LowerTriangular, J::UniformScaling) at linalg/uniformscaling.jl:72
- +(UL::Base.LinAlg.UnitLowerTriangular, J::UniformScaling) at linalg/uniformscaling.jl:75
- +(A::Array, B::SparseMatrixCSC) at sparse/sparsematrix.jl:1462
- +(x::Union{Base.ReshapedArray{T,1,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{T,1}, SubArray{T,1,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where T, y::AbstractSparseArray{Tv,Ti,1} where Ti where Tv) at sparse/sparsevector.jl:1333
- +(x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/periods.jl:358
- +(A::SparseMatrixCSC, J::UniformScaling) at sparse/sparsematrix.jl:3512
- +{TA, TJ}(A::AbstractArray{TA,2}, J::UniformScaling{TJ}) at linalg/uniformscaling.jl:119
- +(A::Diagonal, B::Bidiagonal) at linalg/special.jl:113
- +(A::Bidiagonal, B::Diagonal) at linalg/special.jl:114
- +(A::Diagonal, B::Tridiagonal) at linalg/special.jl:113
- +(A::Tridiagonal, B::Diagonal) at linalg/special.jl:114
- +(A::Diagonal, B::Array{T,2} where T) at linalg/special.jl:113
- +(A::Array{T,2} where T, B::Diagonal) at linalg/special.jl:114
- +(A::Bidiagonal, B::Tridiagonal) at linalg/special.jl:113
- +(A::Tridiagonal, B::Bidiagonal) at linalg/special.jl:114
- +(A::Bidiagonal, B::Array{T,2} where T) at linalg/special.jl:113
- +(A::Array{T,2} where T, B::Bidiagonal) at linalg/special.jl:114
- +(A::Tridiagonal, B::Array{T,2} where T) at linalg/special.jl:113
- +(A::Array{T,2} where T, B::Tridiagonal) at linalg/special.jl:114
- +(A::SymTridiagonal, B::Tridiagonal) at linalg/special.jl:122
- +(A::Tridiagonal, B::SymTridiagonal) at linalg/special.jl:123
- +(A::SymTridiagonal, B::Array{T,2} where T) at linalg/special.jl:122
- +(A::Array{T,2} where T, B::SymTridiagonal) at linalg/special.jl:123
- +(A::Diagonal, B::SymTridiagonal) at linalg/special.jl:131
- +(A::SymTridiagonal, B::Diagonal) at linalg/special.jl:132
- +(A::Bidiagonal, B::SymTridiagonal) at linalg/special.jl:131
- +(A::SymTridiagonal, B::Bidiagonal) at linalg/special.jl:132
- +(A::Diagonal, B::UpperTriangular) at linalg/special.jl:143
- +(A::UpperTriangular, B::Diagonal) at linalg/special.jl:144
- +(A::Diagonal, B::Base.LinAlg.UnitUpperTriangular) at linalg/special.jl:143
- +(A::Base.LinAlg.UnitUpperTriangular, B::Diagonal) at linalg/special.jl:144
- +(A::Diagonal, B::LowerTriangular) at linalg/special.jl:143
- +(A::LowerTriangular, B::Diagonal) at linalg/special.jl:144
- +(A::Diagonal, B::Base.LinAlg.UnitLowerTriangular) at linalg/special.jl:143
- +(A::Base.LinAlg.UnitLowerTriangular, B::Diagonal) at linalg/special.jl:144
- +(A::Base.LinAlg.AbstractTriangular, B::SymTridiagonal) at linalg/special.jl:150
- +(A::SymTridiagonal, B::Base.LinAlg.AbstractTriangular) at linalg/special.jl:151
- +(A::Base.LinAlg.AbstractTriangular, B::Tridiagonal) at linalg/special.jl:150
- +(A::Tridiagonal, B::Base.LinAlg.AbstractTriangular) at linalg/special.jl:151
- +(A::Base.LinAlg.AbstractTriangular, B::Bidiagonal) at linalg/special.jl:150
- +(A::Bidiagonal, B::Base.LinAlg.AbstractTriangular) at linalg/special.jl:151
- +(A::Base.LinAlg.AbstractTriangular, B::Array{T,2} where T) at linalg/special.jl:150
- +(A::Array{T,2} where T, B::Base.LinAlg.AbstractTriangular) at linalg/special.jl:151
- +(Y::Union{Base.ReshapedArray{#s266,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s266,N}, SubArray{#s266,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s266<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/periods.jl:363
- +(X::Union{Base.ReshapedArray{#s265,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s265,N}, SubArray{#s265,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s265<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, Y::Union{Base.ReshapedArray{#s264,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s264,N}, SubArray{#s264,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s264<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/periods.jl:364
- +(x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, y::Base.Dates.TimeType) at dates/arithmetic.jl:86
- +(r::Range{#s267} where #s267<:Base.Dates.TimeType, x::Base.Dates.Period) at dates/ranges.jl:47
- +(A::SparseMatrixCSC, B::SparseMatrixCSC) at sparse/sparsematrix.jl:1458
- +(A::SparseMatrixCSC, B::Array) at sparse/sparsematrix.jl:1461
- +(x::AbstractSparseArray{Tv,Ti,1} where Ti where Tv, y::AbstractSparseArray{Tv,Ti,1} where Ti where Tv) at sparse/sparsevector.jl:1332
- +(x::AbstractSparseArray{Tv,Ti,1} where Ti where Tv, y::Union{Base.ReshapedArray{T,1,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{T,1}, SubArray{T,1,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where T) at sparse/sparsevector.jl:1334
- +(x::AbstractArray{#s45,N} where N where #s45<:Number) at abstractarraymath.jl:93
- +(A::AbstractArray, B::AbstractArray) at arraymath.jl:37
- +(A::Number, B::AbstractArray) at arraymath.jl:44
- +(A::AbstractArray, B::Number) at arraymath.jl:47
- +{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) at multidimensional.jl:70
- +{N}(index::CartesianIndex{N}, i::Integer) at multidimensional.jl:80
- +(J1::UniformScaling, J2::UniformScaling) at linalg/uniformscaling.jl:58
- +(J::UniformScaling, B::BitArray{2}) at linalg/uniformscaling.jl:60
- +(J::UniformScaling, A::AbstractArray{T,2} where T) at linalg/uniformscaling.jl:61
- +{T}(a::Base.Pkg.Resolve.VersionWeights.HierarchicalValue{T}, b::Base.Pkg.Resolve.VersionWeights.HierarchicalValue{T}) at pkg/resolve/versionweight.jl:23
- +{P<:Base.Dates.Period}(x::P, y::P) at dates/periods.jl:70
- +(x::Base.Dates.Period, y::Base.Dates.Period) at dates/periods.jl:346
- +(y::Base.Dates.Period, x::Base.Dates.CompoundPeriod) at dates/periods.jl:348
- +(x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/periods.jl:357
- +(x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, Y::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/periods.jl:362
- +(x::Base.Dates.TimeType) at dates/arithmetic.jl:8
- +(a::Base.Dates.TimeType, b::Base.Dates.Period, c::Base.Dates.Period) at dates/periods.jl:378
- +(a::Base.Dates.TimeType, b::Base.Dates.Period, c::Base.Dates.Period, d::Base.Dates.Period...) at dates/periods.jl:379
- +(x::Base.Dates.TimeType, y::Base.Dates.CompoundPeriod) at dates/periods.jl:382
- +(x::Base.Dates.Instant) at dates/arithmetic.jl:4
- +(y::Base.Dates.Period, x::Base.Dates.TimeType) at dates/arithmetic.jl:83
- +(x::AbstractArray{#s267,N} where N where #s267<:Base.Dates.TimeType, y::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/arithmetic.jl:85
- +(x::Base.Dates.Period, r::Range{#s267} where #s267<:Base.Dates.TimeType) at dates/ranges.jl:46
- +(y::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, x::AbstractArray{#s267,N} where N where #s267<:Base.Dates.TimeType) at dates/arithmetic.jl:87
- +(y::Base.Dates.TimeType, x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) at dates/arithmetic.jl:88
- +(J::UniformScaling, x::Number) at deprecated.jl:56
- +(x::Number, J::UniformScaling) at deprecated.jl:56
- +{C<:Union{ColorTypes.LMS, ColorTypes.XYZ}}(a::C, b::C) at /Users/kenta/.julia/v0.6/Colors/src/algorithms.jl:4
- +(a, b, c, xs...) at operators.jl:424
"
],
"text/plain": [
"# 185 methods for generic function \"+\":\n",
"+(x::Bool, z::Complex{Bool}) in Base at complex.jl:232\n",
"+(x::Bool, y::Bool) in Base at bool.jl:89\n",
"+(x::Bool) in Base at bool.jl:86\n",
"+(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96\n",
"+(x::Bool, z::Complex) in Base at complex.jl:239\n",
"+(a::Float16, b::Float16) in Base at float.jl:372\n",
"+(x::Float32, y::Float32) in Base at float.jl:374\n",
"+(x::Float64, y::Float64) in Base at float.jl:375\n",
"+(z::Complex{Bool}, x::Bool) in Base at complex.jl:233\n",
"+(z::Complex{Bool}, x::Real) in Base at complex.jl:247\n",
"+(x::Char, y::Integer) in Base at char.jl:40\n",
"+(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:312\n",
"+(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:334\n",
"+(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:327\n",
"+(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:321\n",
"+(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:289\n",
"+(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:346\n",
"+(x::BigInt, c::Union{Int16, Int32, Int64, Int8}) in Base.GMP at gmp.jl:362\n",
"+(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat) in Base.MPFR at mpfr.jl:460\n",
"+(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat) in Base.MPFR at mpfr.jl:453\n",
"+(a::BigFloat, b::BigFloat, c::BigFloat) in Base.MPFR at mpfr.jl:447\n",
"+(x::BigFloat, c::BigInt) in Base.MPFR at mpfr.jl:308\n",
"+(x::BigFloat, y::BigFloat) in Base.MPFR at mpfr.jl:277\n",
"+(x::BigFloat, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.MPFR at mpfr.jl:284\n",
"+(x::BigFloat, c::Union{Int16, Int32, Int64, Int8}) in Base.MPFR at mpfr.jl:292\n",
"+(x::BigFloat, c::Union{Float16, Float32, Float64}) in Base.MPFR at mpfr.jl:300\n",
"+(B::BitArray{2}, J::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:59\n",
"+(a::Base.Pkg.Resolve.VersionWeights.VWPreBuildItem, b::Base.Pkg.Resolve.VersionWeights.VWPreBuildItem) in Base.Pkg.Resolve.VersionWeights at pkg/resolve/versionweight.jl:87\n",
"+(a::Base.Pkg.Resolve.VersionWeights.VWPreBuild, b::Base.Pkg.Resolve.VersionWeights.VWPreBuild) in Base.Pkg.Resolve.VersionWeights at pkg/resolve/versionweight.jl:135\n",
"+(a::Base.Pkg.Resolve.VersionWeights.VersionWeight, b::Base.Pkg.Resolve.VersionWeights.VersionWeight) in Base.Pkg.Resolve.VersionWeights at pkg/resolve/versionweight.jl:197\n",
"+(a::Base.Pkg.Resolve.MaxSum.FieldValues.FieldValue, b::Base.Pkg.Resolve.MaxSum.FieldValues.FieldValue) in Base.Pkg.Resolve.MaxSum.FieldValues at pkg/resolve/fieldvalue.jl:44\n",
"+(x::Base.Dates.CompoundPeriod, y::Base.Dates.CompoundPeriod) in Base.Dates at dates/periods.jl:349\n",
"+(x::Base.Dates.CompoundPeriod, y::Base.Dates.Period) in Base.Dates at dates/periods.jl:347\n",
"+(x::Base.Dates.CompoundPeriod, y::Base.Dates.TimeType) in Base.Dates at dates/periods.jl:387\n",
"+(x::Date, y::Base.Dates.Day) in Base.Dates at dates/arithmetic.jl:77\n",
"+(x::Date, y::Base.Dates.Week) in Base.Dates at dates/arithmetic.jl:75\n",
"+(dt::Date, z::Base.Dates.Month) in Base.Dates at dates/arithmetic.jl:58\n",
"+(dt::Date, y::Base.Dates.Year) in Base.Dates at dates/arithmetic.jl:32\n",
"+(dt::Date, t::Base.Dates.Time) in Base.Dates at dates/arithmetic.jl:20\n",
"+(t::Base.Dates.Time, dt::Date) in Base.Dates at dates/arithmetic.jl:24\n",
"+(x::Base.Dates.Time, y::Base.Dates.TimePeriod) in Base.Dates at dates/arithmetic.jl:81\n",
"+(dt::DateTime, z::Base.Dates.Month) in Base.Dates at dates/arithmetic.jl:52\n",
"+(dt::DateTime, y::Base.Dates.Year) in Base.Dates at dates/arithmetic.jl:28\n",
"+(x::DateTime, y::Base.Dates.Period) in Base.Dates at dates/arithmetic.jl:79\n",
"+(a::PyCall.PyObject) in PyCall at /Users/kenta/.julia/v0.6/PyCall/src/pyoperators.jl:36\n",
"+(a::PyCall.PyObject, b) in PyCall at /Users/kenta/.julia/v0.6/PyCall/src/pyoperators.jl:11\n",
"+(y::AbstractFloat, x::Bool) in Base at bool.jl:98\n",
"+(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:32\n",
"+(x::Integer, y::Ptr) in Base at pointer.jl:128\n",
"+(z::Complex, w::Complex) in Base at complex.jl:221\n",
"+(z::Complex, x::Bool) in Base at complex.jl:240\n",
"+(x::Real, z::Complex{Bool}) in Base at complex.jl:246\n",
"+(x::Real, z::Complex) in Base at complex.jl:258\n",
"+(z::Complex, x::Real) in Base at complex.jl:259\n",
"+(x::Rational, y::Rational) in Base at rational.jl:245\n",
"+(x::Integer, y::Char) in Base at char.jl:41\n",
"+(i::Integer, index::CartesianIndex) in Base.IteratorsMD at multidimensional.jl:79\n",
"+(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigInt) in Base.GMP at gmp.jl:350\n",
"+(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) in Base.GMP at gmp.jl:363\n",
"+(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigFloat) in Base.MPFR at mpfr.jl:288\n",
"+(c::Union{Int16, Int32, Int64, Int8}, x::BigFloat) in Base.MPFR at mpfr.jl:296\n",
"+(c::Union{Float16, Float32, Float64}, x::BigFloat) in Base.MPFR at mpfr.jl:304\n",
"+(x::Irrational, y::Irrational) in Base at irrationals.jl:109\n",
"+(x::Real, r::Base.Use_StepRangeLen_Instead) in Base at deprecated.jl:1223\n",
"+(x::FixedPointNumbers.Fixed{T,f}, y::FixedPointNumbers.Fixed{T,f}) where {T, f} in FixedPointNumbers at /Users/kenta/.julia/v0.6/FixedPointNumbers/src/fixed.jl:30\n",
"+(x::FixedPointNumbers.Normed{T,f}, y::FixedPointNumbers.Normed{T,f}) where {T, f} in FixedPointNumbers at /Users/kenta/.julia/v0.6/FixedPointNumbers/src/normed.jl:81\n",
"+(x::Number) in Base at operators.jl:399\n",
"+(x::T, y::T) where T<:Number in Base at promotion.jl:335\n",
"+(x::Number, y::Number) in Base at promotion.jl:249\n",
"+(x::Real, r::AbstractUnitRange) in Base at range.jl:721\n",
"+(x::Number, r::AbstractUnitRange) in Base at range.jl:723\n",
"+(x::Number, r::StepRangeLen) in Base at range.jl:726\n",
"+(x::Number, r::LinSpace) in Base at range.jl:730\n",
"+(x::Number, r::Range) in Base at range.jl:724\n",
"+(r::Range, x::Number) in Base at range.jl:732\n",
"+(r1::OrdinalRange, r2::OrdinalRange) in Base at range.jl:882\n",
"+(r1::LinSpace{T}, r2::LinSpace{T}) where T in Base at range.jl:889\n",
"+(r1::StepRangeLen{T,R,S} where S, r2::StepRangeLen{T,R,S} where S) where {R<:Base.TwicePrecision, T} in Base at twiceprecision.jl:300\n",
"+(r1::StepRangeLen{T,S,S} where S, r2::StepRangeLen{T,S,S} where S) where {T, S} in Base at range.jl:905\n",
"+(r1::Union{LinSpace, OrdinalRange, StepRangeLen}, r2::Union{LinSpace, OrdinalRange, StepRangeLen}) in Base at range.jl:896\n",
"+(x::Base.TwicePrecision, y::Number) in Base at twiceprecision.jl:454\n",
"+(x::Number, y::Base.TwicePrecision) in Base at twiceprecision.jl:457\n",
"+(x::Base.TwicePrecision{T}, y::Base.TwicePrecision{T}) where T in Base at twiceprecision.jl:460\n",
"+(x::Base.TwicePrecision, y::Base.TwicePrecision) in Base at twiceprecision.jl:464\n",
"+(x::Ptr, y::Integer) in Base at pointer.jl:126\n",
"+(A::BitArray, B::BitArray) in Base at bitarray.jl:1176\n",
"+(A::SymTridiagonal, B::SymTridiagonal) in Base.LinAlg at linalg/tridiag.jl:128\n",
"+(A::Tridiagonal, B::Tridiagonal) in Base.LinAlg at linalg/tridiag.jl:624\n",
"+(A::UpperTriangular, B::UpperTriangular) in Base.LinAlg at linalg/triangular.jl:374\n",
"+(A::LowerTriangular, B::LowerTriangular) in Base.LinAlg at linalg/triangular.jl:375\n",
"+(A::UpperTriangular, B::Base.LinAlg.UnitUpperTriangular) in Base.LinAlg at linalg/triangular.jl:376\n",
"+(A::LowerTriangular, B::Base.LinAlg.UnitLowerTriangular) in Base.LinAlg at linalg/triangular.jl:377\n",
"+(A::Base.LinAlg.UnitUpperTriangular, B::UpperTriangular) in Base.LinAlg at linalg/triangular.jl:378\n",
"+(A::Base.LinAlg.UnitLowerTriangular, B::LowerTriangular) in Base.LinAlg at linalg/triangular.jl:379\n",
"+(A::Base.LinAlg.UnitUpperTriangular, B::Base.LinAlg.UnitUpperTriangular) in Base.LinAlg at linalg/triangular.jl:380\n",
"+(A::Base.LinAlg.UnitLowerTriangular, B::Base.LinAlg.UnitLowerTriangular) in Base.LinAlg at linalg/triangular.jl:381\n",
"+(A::Base.LinAlg.AbstractTriangular, B::Base.LinAlg.AbstractTriangular) in Base.LinAlg at linalg/triangular.jl:382\n",
"+(A::Symmetric, x::Bool) in Base.LinAlg at linalg/symmetric.jl:272\n",
"+(A::Symmetric, x::Number) in Base.LinAlg at linalg/symmetric.jl:274\n",
"+(A::Hermitian, x::Bool) in Base.LinAlg at linalg/symmetric.jl:272\n",
"+(A::Hermitian, x::Real) in Base.LinAlg at linalg/symmetric.jl:274\n",
"+(Da::Diagonal, Db::Diagonal) in Base.LinAlg at linalg/diagonal.jl:140\n",
"+(A::Bidiagonal, B::Bidiagonal) in Base.LinAlg at linalg/bidiag.jl:330\n",
"+(UL::UpperTriangular, J::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:72\n",
"+(UL::Base.LinAlg.UnitUpperTriangular, J::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:75\n",
"+(UL::LowerTriangular, J::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:72\n",
"+(UL::Base.LinAlg.UnitLowerTriangular, J::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:75\n",
"+(A::Array, B::SparseMatrixCSC) in Base.SparseArrays at sparse/sparsematrix.jl:1462\n",
"+(x::Union{Base.ReshapedArray{T,1,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{T,1}, SubArray{T,1,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where T, y::AbstractSparseArray{Tv,Ti,1} where Ti where Tv) in Base.SparseArrays at sparse/sparsevector.jl:1333\n",
"+(x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/periods.jl:358\n",
"+(A::SparseMatrixCSC, J::UniformScaling) in Base.SparseArrays at sparse/sparsematrix.jl:3512\n",
"+(A::AbstractArray{TA,2}, J::UniformScaling{TJ}) where {TA, TJ} in Base.LinAlg at linalg/uniformscaling.jl:119\n",
"+(A::Diagonal, B::Bidiagonal) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Bidiagonal, B::Diagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::Diagonal, B::Tridiagonal) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Tridiagonal, B::Diagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::Diagonal, B::Array{T,2} where T) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Array{T,2} where T, B::Diagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::Bidiagonal, B::Tridiagonal) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Tridiagonal, B::Bidiagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::Bidiagonal, B::Array{T,2} where T) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Array{T,2} where T, B::Bidiagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::Tridiagonal, B::Array{T,2} where T) in Base.LinAlg at linalg/special.jl:113\n",
"+(A::Array{T,2} where T, B::Tridiagonal) in Base.LinAlg at linalg/special.jl:114\n",
"+(A::SymTridiagonal, B::Tridiagonal) in Base.LinAlg at linalg/special.jl:122\n",
"+(A::Tridiagonal, B::SymTridiagonal) in Base.LinAlg at linalg/special.jl:123\n",
"+(A::SymTridiagonal, B::Array{T,2} where T) in Base.LinAlg at linalg/special.jl:122\n",
"+(A::Array{T,2} where T, B::SymTridiagonal) in Base.LinAlg at linalg/special.jl:123\n",
"+(A::Diagonal, B::SymTridiagonal) in Base.LinAlg at linalg/special.jl:131\n",
"+(A::SymTridiagonal, B::Diagonal) in Base.LinAlg at linalg/special.jl:132\n",
"+(A::Bidiagonal, B::SymTridiagonal) in Base.LinAlg at linalg/special.jl:131\n",
"+(A::SymTridiagonal, B::Bidiagonal) in Base.LinAlg at linalg/special.jl:132\n",
"+(A::Diagonal, B::UpperTriangular) in Base.LinAlg at linalg/special.jl:143\n",
"+(A::UpperTriangular, B::Diagonal) in Base.LinAlg at linalg/special.jl:144\n",
"+(A::Diagonal, B::Base.LinAlg.UnitUpperTriangular) in Base.LinAlg at linalg/special.jl:143\n",
"+(A::Base.LinAlg.UnitUpperTriangular, B::Diagonal) in Base.LinAlg at linalg/special.jl:144\n",
"+(A::Diagonal, B::LowerTriangular) in Base.LinAlg at linalg/special.jl:143\n",
"+(A::LowerTriangular, B::Diagonal) in Base.LinAlg at linalg/special.jl:144\n",
"+(A::Diagonal, B::Base.LinAlg.UnitLowerTriangular) in Base.LinAlg at linalg/special.jl:143\n",
"+(A::Base.LinAlg.UnitLowerTriangular, B::Diagonal) in Base.LinAlg at linalg/special.jl:144\n",
"+(A::Base.LinAlg.AbstractTriangular, B::SymTridiagonal) in Base.LinAlg at linalg/special.jl:150\n",
"+(A::SymTridiagonal, B::Base.LinAlg.AbstractTriangular) in Base.LinAlg at linalg/special.jl:151\n",
"+(A::Base.LinAlg.AbstractTriangular, B::Tridiagonal) in Base.LinAlg at linalg/special.jl:150\n",
"+(A::Tridiagonal, B::Base.LinAlg.AbstractTriangular) in Base.LinAlg at linalg/special.jl:151\n",
"+(A::Base.LinAlg.AbstractTriangular, B::Bidiagonal) in Base.LinAlg at linalg/special.jl:150\n",
"+(A::Bidiagonal, B::Base.LinAlg.AbstractTriangular) in Base.LinAlg at linalg/special.jl:151\n",
"+(A::Base.LinAlg.AbstractTriangular, B::Array{T,2} where T) in Base.LinAlg at linalg/special.jl:150\n",
"+(A::Array{T,2} where T, B::Base.LinAlg.AbstractTriangular) in Base.LinAlg at linalg/special.jl:151\n",
"+(Y::Union{Base.ReshapedArray{#s266,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s266,N}, SubArray{#s266,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s266<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/periods.jl:363\n",
"+(X::Union{Base.ReshapedArray{#s265,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s265,N}, SubArray{#s265,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s265<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, Y::Union{Base.ReshapedArray{#s264,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s264,N}, SubArray{#s264,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s264<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/periods.jl:364\n",
"+(x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, y::Base.Dates.TimeType) in Base.Dates at dates/arithmetic.jl:86\n",
"+(r::Range{#s267} where #s267<:Base.Dates.TimeType, x::Base.Dates.Period) in Base.Dates at dates/ranges.jl:47\n",
"+(A::SparseMatrixCSC, B::SparseMatrixCSC) in Base.SparseArrays at sparse/sparsematrix.jl:1458\n",
"+(A::SparseMatrixCSC, B::Array) in Base.SparseArrays at sparse/sparsematrix.jl:1461\n",
"+(x::AbstractSparseArray{Tv,Ti,1} where Ti where Tv, y::AbstractSparseArray{Tv,Ti,1} where Ti where Tv) in Base.SparseArrays at sparse/sparsevector.jl:1332\n",
"+(x::AbstractSparseArray{Tv,Ti,1} where Ti where Tv, y::Union{Base.ReshapedArray{T,1,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{T,1}, SubArray{T,1,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where T) in Base.SparseArrays at sparse/sparsevector.jl:1334\n",
"+(x::AbstractArray{#s45,N} where N where #s45<:Number) in Base at abstractarraymath.jl:93\n",
"+(A::AbstractArray, B::AbstractArray) in Base at arraymath.jl:37\n",
"+(A::Number, B::AbstractArray) in Base at arraymath.jl:44\n",
"+(A::AbstractArray, B::Number) in Base at arraymath.jl:47\n",
"+(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where N in Base.IteratorsMD at multidimensional.jl:70\n",
"+(index::CartesianIndex{N}, i::Integer) where N in Base.IteratorsMD at multidimensional.jl:80\n",
"+(J1::UniformScaling, J2::UniformScaling) in Base.LinAlg at linalg/uniformscaling.jl:58\n",
"+(J::UniformScaling, B::BitArray{2}) in Base.LinAlg at linalg/uniformscaling.jl:60\n",
"+(J::UniformScaling, A::AbstractArray{T,2} where T) in Base.LinAlg at linalg/uniformscaling.jl:61\n",
"+(a::Base.Pkg.Resolve.VersionWeights.HierarchicalValue{T}, b::Base.Pkg.Resolve.VersionWeights.HierarchicalValue{T}) where T in Base.Pkg.Resolve.VersionWeights at pkg/resolve/versionweight.jl:23\n",
"+(x::P, y::P) where P<:Base.Dates.Period in Base.Dates at dates/periods.jl:70\n",
"+(x::Base.Dates.Period, y::Base.Dates.Period) in Base.Dates at dates/periods.jl:346\n",
"+(y::Base.Dates.Period, x::Base.Dates.CompoundPeriod) in Base.Dates at dates/periods.jl:348\n",
"+(x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/periods.jl:357\n",
"+(x::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, Y::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/periods.jl:362\n",
"+(x::Base.Dates.TimeType) in Base.Dates at dates/arithmetic.jl:8\n",
"+(a::Base.Dates.TimeType, b::Base.Dates.Period, c::Base.Dates.Period) in Base.Dates at dates/periods.jl:378\n",
"+(a::Base.Dates.TimeType, b::Base.Dates.Period, c::Base.Dates.Period, d::Base.Dates.Period...) in Base.Dates at dates/periods.jl:379\n",
"+(x::Base.Dates.TimeType, y::Base.Dates.CompoundPeriod) in Base.Dates at dates/periods.jl:382\n",
"+(x::Base.Dates.Instant) in Base.Dates at dates/arithmetic.jl:4\n",
"+(y::Base.Dates.Period, x::Base.Dates.TimeType) in Base.Dates at dates/arithmetic.jl:83\n",
"+(x::AbstractArray{#s267,N} where N where #s267<:Base.Dates.TimeType, y::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/arithmetic.jl:85\n",
"+(x::Base.Dates.Period, r::Range{#s267} where #s267<:Base.Dates.TimeType) in Base.Dates at dates/ranges.jl:46\n",
"+(y::Union{Base.Dates.CompoundPeriod, Base.Dates.Period}, x::AbstractArray{#s267,N} where N where #s267<:Base.Dates.TimeType) in Base.Dates at dates/arithmetic.jl:87\n",
"+(y::Base.Dates.TimeType, x::Union{Base.ReshapedArray{#s267,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray, DenseArray{#s267,N}, SubArray{#s267,N,A,I,L} where L} where I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex, Int64, Range{Int64}},N} where N} where A<:Union{Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:DenseArray where N where T, DenseArray} where N where #s267<:Union{Base.Dates.CompoundPeriod, Base.Dates.Period}) in Base.Dates at dates/arithmetic.jl:88\n",
"+(J::UniformScaling, x::Number) in Base at deprecated.jl:56\n",
"+(x::Number, J::UniformScaling) in Base at deprecated.jl:56\n",
"+(a::C, b::C) where C<:Union{ColorTypes.LMS, ColorTypes.XYZ} in Colors at /Users/kenta/.julia/v0.6/Colors/src/algorithms.jl:4\n",
"+(a, b, c, xs...) in Base at operators.jl:424"
]
},
"execution_count": 97,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"methods(+)"
]
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"5-element Array{Method,1}:- +(x::BigInt, c::Union{Int16, Int32, Int64, Int8}) at gmp.jl:362
- +(x::BigFloat, c::Union{Int16, Int32, Int64, Int8}) at mpfr.jl:292
- +{T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}}(x::T, y::T) at int.jl:32
- +(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) at gmp.jl:363
- +(c::Union{Int16, Int32, Int64, Int8}, x::BigFloat) at mpfr.jl:296
"
],
"text/plain": [
"5-element Array{Method,1}:\n",
" +(x::BigInt, c::Union{Int16, Int32, Int64, Int8}) in Base.GMP at gmp.jl:362 \n",
" +(x::BigFloat, c::Union{Int16, Int32, Int64, Int8}) in Base.MPFR at mpfr.jl:292 \n",
" +(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:32\n",
" +(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) in Base.GMP at gmp.jl:363 \n",
" +(c::Union{Int16, Int32, Int64, Int8}, x::BigFloat) in Base.MPFR at mpfr.jl:296 "
]
},
"execution_count": 98,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"methodswith(Int, +)"
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"1 + 1"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"struct Point{T}\n",
" x::T\n",
" y::T\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 101,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"Base.:(+)(p::Point, q::Point) = Point(p.x + q.x, p.y + q.y)"
]
},
{
"cell_type": "code",
"execution_count": 102,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"+ (generic function with 186 methods)"
]
},
"execution_count": 102,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"+"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(-2, 4)"
]
},
"execution_count": 103,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p = Point(1, 2)\n",
"q = Point(-2, 4)"
]
},
{
"cell_type": "code",
"execution_count": 104,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(-1, 6)"
]
},
"execution_count": 104,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p + q"
]
},
{
"cell_type": "code",
"execution_count": 105,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mMethodError: no method matching +(::Point{Int64}, ::Int64)\u001b[0m\nClosest candidates are:\n +(::Any, ::Any, \u001b[91m::Any\u001b[39m, \u001b[91m::Any...\u001b[39m) at operators.jl:424\n +(\u001b[91m::Complex{Bool}\u001b[39m, ::Real) at complex.jl:247\n +(\u001b[91m::Char\u001b[39m, ::Integer) at char.jl:40\n ...\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mMethodError: no method matching +(::Point{Int64}, ::Int64)\u001b[0m\nClosest candidates are:\n +(::Any, ::Any, \u001b[91m::Any\u001b[39m, \u001b[91m::Any...\u001b[39m) at operators.jl:424\n +(\u001b[91m::Complex{Bool}\u001b[39m, ::Real) at complex.jl:247\n +(\u001b[91m::Char\u001b[39m, ::Integer) at char.jl:40\n ...\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"p + 1"
]
},
{
"cell_type": "code",
"execution_count": 106,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"Base.:(+)(p::Point, d::Real) = Point(p.x + d, p.y + d)"
]
},
{
"cell_type": "code",
"execution_count": 107,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(2, 3)"
]
},
"execution_count": 107,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p + 1"
]
},
{
"cell_type": "code",
"execution_count": 108,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"Base.:(*)(p::Point, s::Real) = Point(p.x * s, p.y * s)"
]
},
{
"cell_type": "code",
"execution_count": 109,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(3, 6)"
]
},
"execution_count": 109,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p * 3"
]
},
{
"cell_type": "code",
"execution_count": 110,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 110,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(p + 1) * 3 == p * 3 + 3"
]
},
{
"cell_type": "code",
"execution_count": 111,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"distance (generic function with 1 method)"
]
},
"execution_count": 111,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function distance(p::Point)\n",
" return sqrt(p.x^2 + p.y^2)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 112,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2.23606797749979"
]
},
"execution_count": 112,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"distance(p)"
]
},
{
"cell_type": "code",
"execution_count": 113,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"function Base.:(+)(p::Point, n::Integer)\n",
" println(\"You called Point + Integer!\")\n",
" return Point(p.x + n, p.y + n)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 114,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"You called Point + Integer!\n"
]
},
{
"data": {
"text/plain": [
"Point{Int64}(2, 3)"
]
},
"execution_count": 114,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p + 1"
]
},
{
"cell_type": "code",
"execution_count": 115,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Float64}(2.0, 3.0)"
]
},
"execution_count": 115,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p + 1.0"
]
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"move_right (generic function with 1 method)"
]
},
"execution_count": 116,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function move_right(p::Point)\n",
" return p + Point(1, 0)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(1, 2)"
]
},
"execution_count": 117,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p"
]
},
{
"cell_type": "code",
"execution_count": 118,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Point{Int64}(2, 2)"
]
},
"execution_count": 118,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"move_right(p)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"多重ディスパッチのポイント\n",
"\n",
"- すべての引数の扱いは平等 (右も左もない)\n",
"- メソッドのうち、型が一番良く合うものが実際に呼ばれる"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## C言語との連携"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`ccall`でC言語の関数を呼び出せる"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0"
]
},
"execution_count": 119,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# https://www.gnu.org/software/libc/manual/html_node/Trig-Functions.html\n",
"ccall((:sin, \"libc\"), Cdouble, (Cdouble,), π/2)"
]
},
{
"cell_type": "code",
"execution_count": 120,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"/usr/local/bin/fish\""
]
},
"execution_count": 120,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html\n",
"unsafe_string(ccall((:getenv, \"libc\"), Cstring, (Cstring,), \"SHELL\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"JuliaとCの構造体はメモリレイアウトの互換性があるので、互いに読み書きできる。具体例は以下のパッケージを参照\n",
"- https://github.com/bicycle1885/CodecZlib.jl/blob/master/src/libz.jl\n",
"- https://github.com/bicycle1885/EzXML.jl/blob/master/src/node.jl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ブロードキャスト"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"スカラーや配列を同じ形に揃えて、要素毎の演算をすること。"
]
},
{
"cell_type": "code",
"execution_count": 121,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 4\n",
" 5\n",
" 6"
]
},
"execution_count": 121,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = [1,2,3]; y = [4,5,6]"
]
},
{
"cell_type": "code",
"execution_count": 122,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 3\n",
" 6\n",
" 9"
]
},
"execution_count": 122,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# スカラー倍 (ブロードキャストとは言わない)\n",
"x * 3"
]
},
{
"cell_type": "code",
"execution_count": 123,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 5\n",
" 7\n",
" 9"
]
},
"execution_count": 123,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# ベクトル和 (ブロードキャストとは言わない)\n",
"x + y"
]
},
{
"cell_type": "code",
"execution_count": 124,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 3\n",
" 6\n",
" 9"
]
},
"execution_count": 124,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 要素毎の積 (ブロードキャスト)\n",
"x .* 3"
]
},
{
"cell_type": "code",
"execution_count": 125,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 5\n",
" 7\n",
" 9"
]
},
"execution_count": 125,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 要素毎の和 (ブロードキャスト)\n",
"x .+ y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"列ベクトルと列ベクトルの積は計算できない"
]
},
{
"cell_type": "code",
"execution_count": 126,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mDimensionMismatch(\"Cannot multiply two vectors\")\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mDimensionMismatch(\"Cannot multiply two vectors\")\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1m*\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Array{Int64,1}, ::Array{Int64,1}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./linalg/rowvector.jl:184\u001b[22m\u001b[22m",
" [2] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"x * y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ブロードキャストを使えば要素毎の積なら計算できる"
]
},
{
"cell_type": "code",
"execution_count": 127,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 4\n",
" 10\n",
" 18"
]
},
"execution_count": 127,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x .* y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"列ベクトルと行ベクトルの和は計算できない"
]
},
{
"cell_type": "code",
"execution_count": 128,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mDimensionMismatch(\"dimensions must match\")\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mDimensionMismatch(\"dimensions must match\")\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1mpromote_shape\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}, ::Tuple{Base.OneTo{Int64}}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./indices.jl:79\u001b[22m\u001b[22m",
" [2] \u001b[1mpromote_shape\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Tuple{Base.OneTo{Int64}}, ::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./indices.jl:75\u001b[22m\u001b[22m",
" [3] \u001b[1m+\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Array{Int64,1}, ::RowVector{Int64,Array{Int64,1}}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./arraymath.jl:37\u001b[22m\u001b[22m",
" [4] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"x + y'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ブロードキャストはできる"
]
},
{
"cell_type": "code",
"execution_count": 129,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×3 Array{Int64,2}:\n",
" 5 6 7\n",
" 6 7 8\n",
" 7 8 9"
]
},
"execution_count": 129,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x .+ y'"
]
},
{
"cell_type": "code",
"execution_count": 130,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×2 Array{Int64,2}:\n",
" 1 2\n",
" 3 4\n",
" 5 6"
]
},
"execution_count": 130,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = [\n",
" 1 2\n",
" 3 4\n",
" 5 6\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"行列と列ベクトルの和は計算できない"
]
},
{
"cell_type": "code",
"execution_count": 131,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mDimensionMismatch(\"dimensions must match\")\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mDimensionMismatch(\"dimensions must match\")\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1mpromote_shape\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}, ::Tuple{Base.OneTo{Int64}}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./indices.jl:84\u001b[22m\u001b[22m",
" [2] \u001b[1m+\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::Array{Int64,2}, ::Array{Int64,1}\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./arraymath.jl:37\u001b[22m\u001b[22m",
" [3] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"A + x"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ブロードキャストはできる"
]
},
{
"cell_type": "code",
"execution_count": 132,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3×2 Array{Int64,2}:\n",
" 2 3\n",
" 5 6\n",
" 8 9"
]
},
"execution_count": 132,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A .+ x"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## マクロ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- 関数では実現できない、コードの操作ができる\n",
"- Cのマクロとは異なるLispから受け継いだマクロ"
]
},
{
"cell_type": "code",
"execution_count": 133,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-3"
]
},
"execution_count": 133,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = -3"
]
},
{
"cell_type": "code",
"execution_count": 134,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x = -3\n"
]
}
],
"source": [
"@show x;"
]
},
{
"cell_type": "code",
"execution_count": 135,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mAssertionError: x > 0\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mAssertionError: x > 0\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"@assert x > 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"標準ライブラリで提供されているマクロは何種類かに分けられる。\n",
"\n",
"1. 開発支援系: `@show`, `@less`, `@which`, `@code_warntype`, etc.\n",
"2. 特殊構文系: `@assert`, `@goto`, `@label`, `@async`, `@parallel`, etc.\n",
"3. コンパイラヒント系: `@inbounds`, `@inline`, `@fastmath`, etc.\n",
"4. メタデータ系: `@__DIR__`, `@__FILE__`, etc.\n",
"5. 非標準文字列系: `@r_str`, `@ip_str`, `@v_str`, etc."
]
},
{
"cell_type": "code",
"execution_count": 136,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 136,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ismatch(r\"0x[0-9A-Fa-f]{2}\", \"0x3F\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Juliaの実行モデル"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Juliaの実行モデルを理解することは速いコードを書く上で非常に重要\n",
"- Juliaはちょっと特殊な実行の仕方をするので、最初は少し戸惑う"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Juliaは本当に速い?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"答: 速い\n",
"\n",
"現時点でC/C++より遅くなりそうなケース\n",
"- マルチスレッドプログラミング (理由: Juliaのマルチスレッドサポートが弱い)\n",
"- 細かいSIMDを使ったプログラミング (理由: x86のSIMD intrinsicsがない)\n",
"\n",
"これ以外のケースでは、バグでないJuliaの制約でパフォーマンスが出なかったことは体験してない(個人の感想です)。\n",
"\n",
"希望の光\n",
"- より柔軟なマルチスレッドのサポートが開発中 (https://github.com/JuliaLang/julia/pull/22631)\n",
"- `llvmcall`命令で細かいSIMDの制御もできないことはない? (https://github.com/eschnett/SIMD.jl)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"具体例: Base64のデコーダー\n",
"\n",
"64+1種類のASCII文字を使ってエンコードされたバイナリデータを元のデータに復元する。\n",
"\n",
"ポイント\n",
"- 4バイトのASCII文字列にエンコードされたデータを3バイトのバイナリに変換\n",
"- 特定の文字の無視・パディングの処理などがあり、それなりに複雑\n",
"- 表引きによるアルゴリズム\n",
"\n",
"```julia\n",
"function TranscodingStreams.process(\n",
" codec :: Base64Decoder,\n",
" input :: Memory,\n",
" output :: Memory,\n",
" error :: Error)\n",
" table = codec.table\n",
" state = codec.state\n",
" buffer = codec.buffer\n",
"\n",
" # Check if we can encode data.\n",
" if !is_running(state)\n",
" error[] = ArgumentError(\"decoding is already finished\")\n",
" return 0, 0, :error\n",
" elseif output.size < 3\n",
" # Need more output space.\n",
" return 0, 0, :ok\n",
" end\n",
"\n",
" # Load the frist bytes.\n",
" i = j = 0\n",
" while buffer.size < 3 && i < input.size\n",
" buffer[buffer.size+=1] = input[i+=1]\n",
" end\n",
" c1 = c2 = c3 = c4 = BASE64_CODEIGN\n",
" if buffer.size ≥ 1\n",
" c1 = decode(table, buffer[1])\n",
" end\n",
" if buffer.size ≥ 2\n",
" c2 = decode(table, buffer[2])\n",
" end\n",
" if buffer.size ≥ 3\n",
" c3 = decode(table, buffer[3])\n",
" end\n",
" empty!(buffer)\n",
"\n",
" # Start decoding loop.\n",
" status = :ok\n",
" @inbounds while true\n",
" if c1 > 0x3f || c2 > 0x3f || c3 > 0x3f || c4 > 0x3f\n",
" i, j, status = decode_irregular(table, c1, c2, c3, c4, input, i, output, j, error)\n",
" else\n",
" output[j+1] = c1 << 2 | c2 >> 4\n",
" output[j+2] = c2 << 4 | c3 >> 2\n",
" output[j+3] = c3 << 6 | c4\n",
" j += 3\n",
" end\n",
" if i + 4 ≤ input.size && j + 3 ≤ output.size && status == :ok\n",
" c1 = decode(table, input[i+1])\n",
" c2 = decode(table, input[i+2])\n",
" c3 = decode(table, input[i+3])\n",
" c4 = decode(table, input[i+4])\n",
" i += 4\n",
" else\n",
" break\n",
" end\n",
" end\n",
"\n",
" # Epilogue.\n",
" if status == :end || status == :error\n",
" finish!(state)\n",
" end\n",
" return i, j, status\n",
"end\n",
"\n",
"# Decode irregular code (e.g. non-alphabet, padding, etc.).\n",
"function decode_irregular(table, c1, c2, c3, c4, input, i, output, j, error)\n",
" # Skip ignored chars.\n",
" while true\n",
" if c1 == BASE64_CODEIGN\n",
" c1, c2, c3 = c2, c3, c4\n",
" elseif c2 == BASE64_CODEIGN\n",
" c2, c3 = c3, c4\n",
" elseif c3 == BASE64_CODEIGN\n",
" c3 = c4\n",
" elseif c4 == BASE64_CODEIGN\n",
" # pass\n",
" else\n",
" break\n",
" end\n",
" if i + 1 ≤ input.size\n",
" c4 = decode(table, input[i+=1])\n",
" else\n",
" c4 = BASE64_CODEEND\n",
" break\n",
" end\n",
" end\n",
"\n",
" # Write output.\n",
" if c1 ≤ 0x3f && c2 ≤ 0x3f && c3 ≤ 0x3f && c4 ≤ 0x3f\n",
" output[j+=1] = c1 << 2 | c2 >> 4\n",
" output[j+=1] = c2 << 4 | c3 >> 2\n",
" output[j+=1] = c3 << 6 | c4\n",
" status = :ok\n",
" elseif c1 ≤ 0x3f && c2 ≤ 0x3f && c3 ≤ 0x3f && c4 == BASE64_CODEPAD\n",
" c4 = 0x00\n",
" output[j+=1] = c1 << 2 | c2 >> 4\n",
" output[j+=1] = c2 << 4 | c3 >> 2\n",
" status = :end\n",
" elseif c1 ≤ 0x3f && c2 ≤ 0x3f && c3 == c4 == BASE64_CODEPAD\n",
" c3 = c4 = 0x00\n",
" output[j+=1] = c1 << 2 | c2 >> 4\n",
" status = :end\n",
" elseif c1 == c2 == c3 == BASE64_CODEIGN && c4 == BASE64_CODEEND\n",
" status = :end\n",
" else\n",
" error[] = ArgumentError(\"invalid data\")\n",
" status = :error\n",
" end\n",
" return i, j, status\n",
"end\n",
"```\n",
"\n",
"\n",
"\n",
"ベンチマーク\n",
"\n",
"Pythonの標準ライブラリのC言語による実装より高速\n",
"\n",
"Julia 0.6.0:\n",
"```\n",
"julia> sizeof(data)\n",
"286180\n",
"\n",
"julia> @benchmark transcode(Base64Decoder(), data)\n",
"BenchmarkTools.Trial:\n",
" memory estimate: 490.31 KiB\n",
" allocs estimate: 19\n",
" --------------\n",
" minimum time: 372.894 μs (0.00% GC)\n",
" median time: 561.580 μs (0.00% GC)\n",
" mean time: 594.615 μs (6.84% GC)\n",
" maximum time: 4.291 ms (68.99% GC)\n",
" --------------\n",
" samples: 8379\n",
" evals/sample: 1\n",
"\n",
"```\n",
"\n",
"Python 3.5.2:\n",
"```\n",
"In [13]: len(data)\n",
"Out[13]: 286180\n",
"\n",
"In [14]: %timeit base64.decodebytes(data)\n",
"1.16 ms ± 14.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n",
"\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 実行するまでの流れ\n",
"\n",
"ユーザーがREPLに打ち込んだ処理が実行されるまでの流れ\n",
"\n",
"1. コンパイラーがJuliaのソースコードをパースする\n",
"2. マクロ・構文糖衣の展開などを行う\n",
"3. 低レベルなJuliaの中間表現に落とし込む\n",
"4. 型推論を行う\n",
"5. LLVMの中間表現に落とし込む\n",
"6. ネイティブコードに落とし込む\n",
"7. 実行する"
]
},
{
"cell_type": "code",
"execution_count": 137,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
":(1 + 1)"
]
},
"execution_count": 137,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# ソースコードのパース\n",
"parse(\"1 + 1\")"
]
},
{
"cell_type": "code",
"execution_count": 138,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
":(function foobar(x) # none, line 2:\n",
" @assert x > 0\n",
" end)"
]
},
"execution_count": 138,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parse(\"\"\"\n",
"function foobar(x)\n",
" @assert x > 0\n",
"end\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`parse`は`Expr`のオブジェクトを返す。`Expr`は抽象構文木(AST)。"
]
},
{
"cell_type": "code",
"execution_count": 139,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
":(1 + 2 * 3)"
]
},
"execution_count": 139,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr = parse(\"1 + 2 * 3\")"
]
},
{
"cell_type": "code",
"execution_count": 140,
"metadata": {},
"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: Expr\n",
" head: Symbol call\n",
" args: Array{Any}((3,))\n",
" 1: Symbol *\n",
" 2: Int64 2\n",
" 3: Int64 3\n",
" typ: Any\n",
" typ: Any\n"
]
}
],
"source": [
"dump(expr)"
]
},
{
"cell_type": "code",
"execution_count": 141,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"quote # In[141], line 3:\n",
" if x < 0 # In[141], line 4:\n",
" println(\"x is negative\")\n",
" else # In[141], line 5:\n",
" if x == 0 # In[141], line 6:\n",
" println(\"x is zero\")\n",
" else # In[141], line 8:\n",
" println(\"x is positive\")\n",
" end\n",
" end\n",
"end"
]
},
"execution_count": 141,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# ifelseなどは複数のif-elseに展開される\n",
"quote\n",
" if x < 0\n",
" println(\"x is negative\")\n",
" elseif x == 0\n",
" println(\"x is zero\")\n",
" else\n",
" println(\"x is positive\")\n",
" end\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 142,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
":(1 + 2 * 3)"
]
},
"execution_count": 142,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# マクロの展開する関数\n",
"macroexpand(expr)"
]
},
{
"cell_type": "code",
"execution_count": 143,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
":(if x > 0\n",
" nothing\n",
" else \n",
" (Base.throw)(Base.Main.Base.AssertionError(\"x > 0\"))\n",
" end)"
]
},
"execution_count": 143,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# @から始まるマクロはこの関数で展開される\n",
"macroexpand(:(@assert x > 0))"
]
},
{
"cell_type": "code",
"execution_count": 144,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"quote # In[144], line 2:\n",
" function foobar(x) # In[144], line 3:\n",
" if x > 0\n",
" nothing\n",
" else \n",
" (Base.throw)(Base.Main.Base.AssertionError(\"x > 0\"))\n",
" end\n",
" end\n",
"end"
]
},
"execution_count": 144,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"macroexpand(quote\n",
" function foobar(x)\n",
" @assert x > 0\n",
" end\n",
"end)"
]
},
{
"cell_type": "code",
"execution_count": 145,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"foobar (generic function with 1 method)"
]
},
"execution_count": 145,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function foobar(x)\n",
" @assert x > 0\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 146,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{CodeInfo,1}:\n",
" CodeInfo(:(begin \n",
" nothing\n",
" unless x > 0 goto 4\n",
" return\n",
" 4: \n",
" return (Base.throw)(((Core.getfield)((Core.getfield)(Base.Main, :Base), :AssertionError))(\"x > 0\"))\n",
" end))"
]
},
"execution_count": 146,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Juliaの中間表現はunlessの分岐とgotoばかりのフラットなコード\n",
"code_lowered(foobar, (Int,))"
]
},
{
"cell_type": "code",
"execution_count": 147,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"foobar (generic function with 1 method)"
]
},
"execution_count": 147,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function foobar(n)\n",
" x = 0\n",
" for i in 1:n\n",
" x += i\n",
" end\n",
" return x\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 148,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{CodeInfo,1}:\n",
" CodeInfo(:(begin \n",
" nothing\n",
" x = 0 # line 3:\n",
" SSAValue(0) = (Main.colon)(1, n)\n",
" #temp# = (Base.start)(SSAValue(0))\n",
" 6: \n",
" unless !((Base.done)(SSAValue(0), #temp#)) goto 15\n",
" SSAValue(1) = (Base.next)(SSAValue(0), #temp#)\n",
" i = (Core.getfield)(SSAValue(1), 1)\n",
" #temp# = (Core.getfield)(SSAValue(1), 2) # line 4:\n",
" x = x + i\n",
" 13: \n",
" goto 6\n",
" 15: # line 6:\n",
" return x\n",
" end))"
]
},
"execution_count": 148,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# forループもunlessとgotoへ展開\n",
"code_lowered(foobar, (Int,))"
]
},
{
"cell_type": "code",
"execution_count": 149,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{Any,1}:\n",
" CodeInfo(:(begin \n",
" x = 0 # line 3:\n",
" SSAValue(2) = (Base.select_value)((Base.sle_int)(1, n)::Bool, n, (Base.sub_int)(1, 1)::Int64)::Int64\n",
" #temp# = 1\n",
" 5: \n",
" unless (Base.not_int)((#temp# === (Base.add_int)(SSAValue(2), 1)::Int64)::Bool)::Bool goto 15\n",
" SSAValue(3) = #temp#\n",
" SSAValue(4) = (Base.add_int)(#temp#, 1)::Int64\n",
" i = SSAValue(3)\n",
" #temp# = SSAValue(4) # line 4:\n",
" x = (Base.add_int)(x, i)::Int64\n",
" 13: \n",
" goto 5\n",
" 15: # line 6:\n",
" return x\n",
" end))=>Int64"
]
},
"execution_count": 149,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Juliaの中間表現に型推論で型をつける\n",
"code_typed(foobar, (Int,))"
]
},
{
"cell_type": "code",
"execution_count": 150,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define i64 @julia_foobar_63146(i64) #0 !dbg !5 {\n",
"top:\n",
" %1 = icmp slt i64 %0, 1\n",
" br i1 %1, label %L15, label %if.lr.ph\n",
"\n",
"if.lr.ph: ; preds = %top\n",
" %2 = shl i64 %0, 1\n",
" %3 = add i64 %0, -1\n",
" %4 = zext i64 %3 to i65\n",
" %5 = add i64 %0, -2\n",
" %6 = zext i64 %5 to i65\n",
" %7 = mul i65 %4, %6\n",
" %8 = lshr i65 %7, 1\n",
" %9 = trunc i65 %8 to i64\n",
" %10 = add i64 %2, %9\n",
" %11 = add i64 %10, -1\n",
" br label %L15\n",
"\n",
"L15: ; preds = %if.lr.ph, %top\n",
" %x.0.lcssa = phi i64 [ %11, %if.lr.ph ], [ 0, %top ]\n",
" ret i64 %x.0.lcssa\n",
"}\n"
]
}
],
"source": [
"# LLVM中間表現に変換\n",
"code_llvm(foobar, (Int,))"
]
},
{
"cell_type": "code",
"execution_count": 151,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\t.section\t__TEXT,__text,regular,pure_instructions\n",
"Filename: In[147]\n",
"\tpushq\t%rbp\n",
"\tmovq\t%rsp, %rbp\n",
"\txorl\t%eax, %eax\n",
"Source line: 3\n",
"\ttestq\t%rdi, %rdi\n",
"\tjle\tL34\n",
"\tleaq\t-1(%rdi), %rdx\n",
"\tleaq\t-2(%rdi), %rax\n",
"\tmulxq\t%rax, %rax, %rcx\n",
"\tshldq\t$63, %rax, %rcx\n",
"\tleaq\t-1(%rcx,%rdi,2), %rax\n",
"Source line: 6\n",
"L34:\n",
"\tpopq\t%rbp\n",
"\tretq\n",
"\tnopw\t%cs:(%rax,%rax)\n"
]
}
],
"source": [
"# nativeコードに変換\n",
"code_native(foobar, (Int,))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"REPLにコードを打ち込むと上の処理を行う"
]
},
{
"cell_type": "code",
"execution_count": 152,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"55"
]
},
"execution_count": 152,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"foobar(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 特殊化 (specialization)"
]
},
{
"cell_type": "code",
"execution_count": 153,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"foobar (generic function with 1 method)"
]
},
"execution_count": 153,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function foobar(n)\n",
" return n * 2\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 154,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin \n",
" return (Base.mul_int)(n, 2)::Int64\n",
" end))=>Int64"
]
},
"execution_count": 154,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed foobar(1)"
]
},
{
"cell_type": "code",
"execution_count": 155,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin \n",
" return (Base.mul_float)(n, (Base.sitofp)(Float64, 2)::Float64)::Float64\n",
" end))=>Float64"
]
},
"execution_count": 155,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed foobar(1.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- 引数の型が異なれば、型推論の結果も違う\n",
"- 関数は引数の型の組み合わせだけ特殊化(specialize)される"
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"foobar (generic function with 1 method)"
]
},
"execution_count": 156,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function foobar(n)\n",
" if n isa Integer\n",
" println(\"Integer!\")\n",
" end\n",
" return n * 2\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Integer!\n"
]
},
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"foobar(1)"
]
},
{
"cell_type": "code",
"execution_count": 158,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2.0"
]
},
"execution_count": 158,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"foobar(1.0)"
]
},
{
"cell_type": "code",
"execution_count": 159,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin # line 3:\n",
" $(Expr(:inbounds, false))\n",
" # meta: location coreio.jl println 5\n",
" SSAValue(0) = (Core.typeassert)(Base.STDOUT, Base.IO)::IO\n",
" # meta: pop location\n",
" $(Expr(:inbounds, :pop))\n",
" (Base.print)(SSAValue(0), \"Integer!\", $(QuoteNode('\\n')))::Void\n",
" 8: # line 5:\n",
" return (Base.mul_int)(n, 2)::Int64\n",
" end))=>Int64"
]
},
"execution_count": 159,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed foobar(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"特殊化によりprintlnが分岐ごと消えている!"
]
},
{
"cell_type": "code",
"execution_count": 160,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin \n",
" goto 3 # line 3:\n",
" 3: # line 5:\n",
" return (Base.mul_float)(n, (Base.sitofp)(Float64, 2)::Float64)::Float64\n",
" end))=>Float64"
]
},
"execution_count": 160,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed foobar(1.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## トップレベル"
]
},
{
"cell_type": "code",
"execution_count": 161,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Int(time_ns() - start_ns) = 87514105\n"
]
},
{
"data": {
"text/plain": [
"87514105"
]
},
"execution_count": 161,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"start_ns = time_ns()\n",
"s = 0.0\n",
"for _ in 1:1_000_000\n",
" s += rand()\n",
"end\n",
"@show Int(time_ns() - start_ns)"
]
},
{
"cell_type": "code",
"execution_count": 162,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"loop (generic function with 1 method)"
]
},
"execution_count": 162,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function loop()\n",
" s = 0.0\n",
" for _ in 1:1_000_000\n",
" s += rand()\n",
" end\n",
" return s\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 163,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Int(time_ns() - start_ns) = 14248780\n"
]
},
{
"data": {
"text/plain": [
"14248780"
]
},
"execution_count": 163,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"start_ns = time_ns()\n",
"s = loop()\n",
"@show Int(time_ns() - start_ns)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- 同じ計算なのに上のコードは20倍くらい遅い!\n",
"- 上のコードはトップレベルで実行されているのに対し、下のコードは関数内のループ\n",
"- トップレベルの処理はJITコンパイルされない!\n",
"\n",
"使い分け:\n",
"- トップレベルでは、関数の定義や関数呼び出しを行う\n",
"- 関数内では、重い処理を行う"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 型の安定性"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Juliaの高速化は、曖昧性の少ないコードを書くこと\n",
"- 型が決定できないとき、Juliaはすごく遅くなる!"
]
},
{
"cell_type": "code",
"execution_count": 164,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"collatz1 (generic function with 1 method)"
]
},
"execution_count": 164,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function collatz1(n)\n",
" step = 0\n",
" while n != 1\n",
" step += 1\n",
" if mod(n, 2) == 0\n",
" n /= 2\n",
" else\n",
" n = n * 3 + 1\n",
" end\n",
" end\n",
" return step\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 165,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 165,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"collatz1(10)"
]
},
{
"cell_type": "code",
"execution_count": 166,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"using BenchmarkTools"
]
},
{
"cell_type": "code",
"execution_count": 167,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 86.06 MiB\n",
" allocs estimate: 5640009\n",
" --------------\n",
" minimum time: 110.469 ms (5.88% GC)\n",
" median time: 116.169 ms (5.97% GC)\n",
" mean time: 117.584 ms (5.84% GC)\n",
" maximum time: 132.606 ms (5.19% GC)\n",
" --------------\n",
" samples: 43\n",
" evals/sample: 1"
]
},
"execution_count": 167,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@benchmark for n in 1:10000; collatz1(n); end"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(:(begin \n",
" n@_4 = n@_2\n",
" step = 0 # line 3:\n",
" 4: \n",
" unless (n@_4 isa Float64)::Bool goto 8\n",
" #temp#@_5 = MethodInstance for !=(::Float64, ::Int64)\n",
" goto 17\n",
" 8: \n",
" unless (n@_4 isa Int64)::Bool goto 12\n",
" #temp#@_5 = MethodInstance for !=(::Int64, ::Int64)\n",
" goto 17\n",
" 12: \n",
" goto 14\n",
" 14: \n",
" #temp#@_6 = (n@_4 != 1)::Bool\n",
" goto 19\n",
" 17: \n",
" #temp#@_6 = $(Expr(:invoke, :(#temp#@_5), :(Main.!=), :(n@_4), 1))\n",
" 19: \n",
" unless #temp#@_6 goto 108 # line 4:\n",
" step = (Base.add_int)(step, 1)::Int64 # line 5:\n",
" unless (n@_4 isa Float64)::Bool goto 27\n",
" #temp#@_7 = MethodInstance for mod(::Float64, ::Int64)\n",
" goto 36\n",
" 27: \n",
" unless (n@_4 isa Int64)::Bool goto 31\n",
" #temp#@_7 = MethodInstance for mod(::Int64, ::Int64)\n",
" goto 36\n",
" 31: \n",
" goto 33\n",
" 33: \n",
" #temp#@_8 = (Main.mod)(n@_4, 2)::Union{Float64, Int64}\n",
" goto 38\n",
" 36: \n",
" #temp#@_8 = $(Expr(:invoke, :(#temp#@_7), :(Main.mod), :(n@_4), 2))\n",
" 38: \n",
" unless (#temp#@_8 isa Float64)::Bool goto 42\n",
" #temp#@_9 = MethodInstance for ==(::Float64, ::Int64)\n",
" goto 51\n",
" 42: \n",
" unless (#temp#@_8 isa Int64)::Bool goto 46\n",
" #temp#@_9 = MethodInstance for ==(::Int64, ::Int64)\n",
" goto 51\n",
" 46: \n",
" goto 48\n",
" 48: \n",
" #temp#@_10 = (#temp#@_8 == 0)::Bool\n",
" goto 53\n",
" 51: \n",
" #temp#@_10 = $(Expr(:invoke, :(#temp#@_9), :(Main.==), :(#temp#@_8), 0))\n",
" 53: \n",
" unless #temp#@_10 goto 73 # line 6:\n",
" unless (n@_4 isa Float64)::Bool goto 59\n",
" #temp#@_11 = MethodInstance for /(::Float64, ::Int64)\n",
" goto 68\n",
" 59: \n",
" unless (n@_4 isa Int64)::Bool goto 63\n",
" #temp#@_11 = MethodInstance for /(::Int64, ::Int64)\n",
" goto 68\n",
" 63: \n",
" goto 65\n",
" 65: \n",
" #temp#@_12 = (n@_4 / 2)::Float64\n",
" goto 70\n",
" 68: \n",
" #temp#@_12 = $(Expr(:invoke, :(#temp#@_11), :(Main./), :(n@_4), 2))\n",
" 70: \n",
" n@_4 = #temp#@_12\n",
" goto 106\n",
" 73: # line 8:\n",
" unless (n@_4 isa Float64)::Bool goto 78\n",
" #temp#@_13 = MethodInstance for *(::Float64, ::Int64)\n",
" goto 87\n",
" 78: \n",
" unless (n@_4 isa Int64)::Bool goto 82\n",
" #temp#@_13 = MethodInstance for *(::Int64, ::Int64)\n",
" goto 87\n",
" 82: \n",
" goto 84\n",
" 84: \n",
" #temp#@_14 = (n@_4 * 3)::Union{Float64, Int64}\n",
" goto 89\n",
" 87: \n",
" #temp#@_14 = $(Expr(:invoke, :(#temp#@_13), :(Main.*), :(n@_4), 3))\n",
" 89: \n",
" unless (#temp#@_14 isa Float64)::Bool goto 93\n",
" #temp#@_15 = MethodInstance for +(::Float64, ::Int64)\n",
" goto 102\n",
" 93: \n",
" unless (#temp#@_14 isa Int64)::Bool goto 97\n",
" #temp#@_15 = MethodInstance for +(::Int64, ::Int64)\n",
" goto 102\n",
" 97: \n",
" goto 99\n",
" 99: \n",
" #temp#@_16 = (#temp#@_14 + 1)::Union{Float64, Int64}\n",
" goto 104\n",
" 102: \n",
" #temp#@_16 = $(Expr(:invoke, :(#temp#@_15), :(Main.+), :(#temp#@_14), 1))\n",
" 104: \n",
" n@_4 = #temp#@_16\n",
" 106: \n",
" goto 4\n",
" 108: # line 11:\n",
" return step\n",
" end))=>Int64"
]
},
"execution_count": 168,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed collatz1(10)"
]
},
{
"cell_type": "code",
"execution_count": 169,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"collatz2 (generic function with 1 method)"
]
},
"execution_count": 169,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function collatz2(n)\n",
" step = 0\n",
" while n != 1\n",
" step += 1\n",
" if mod(n, 2) == 0\n",
" n = div(n, 2)\n",
" else\n",
" n = n * 3 + 1\n",
" end\n",
" end\n",
" return step\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 170,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 170,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"collatz2(10)"
]
},
{
"cell_type": "code",
"execution_count": 171,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 0 bytes\n",
" allocs estimate: 0\n",
" --------------\n",
" minimum time: 3.080 ms (0.00% GC)\n",
" median time: 3.298 ms (0.00% GC)\n",
" mean time: 3.386 ms (0.00% GC)\n",
" maximum time: 17.355 ms (0.00% GC)\n",
" --------------\n",
" samples: 1473\n",
" evals/sample: 1"
]
},
"execution_count": 171,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@benchmark for n in 1:10000; collatz2(n); end"
]
},
{
"cell_type": "code",
"execution_count": 172,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Variables:\n",
" #self#::#collatz2\n",
" n@_2::Int64\n",
" step::Int64\n",
" n@_4::Int64\n",
" d::Int64\n",
" #temp#::Int64\n",
"\n",
"Body:\n",
" begin \n",
" n@_4::Int64 = n@_2::Int64\n",
" step::Int64 = 0 # line 3:\n",
" 4: \n",
" unless (Base.not_int)((n@_4::Int64 === 1)::Bool)::Bool goto 32 # line 4:\n",
" step::Int64 = (Base.add_int)(step::Int64, 1)::Int64 # line 5:\n",
" $(Expr(:inbounds, false))\n",
" # meta: location int.jl mod 170\n",
" unless (2 === -1)::Bool goto 14\n",
" #temp#::Int64 = 0\n",
" goto 20\n",
" 14: # line 171:\n",
" # meta: location int.jl fld 191\n",
" d::Int64 = (Base.checked_sdiv_int)(n@_4::Int64, 2)::Int64\n",
" # meta: pop location\n",
" #temp#::Int64 = (Base.sub_int)(n@_4::Int64, (Base.mul_int)((Base.sub_int)(d::Int64, (Base.and_int)((Base.zext_int)(Int64, (Base.and_int)((Base.slt_int)((Base.xor_int)(n@_4::Int64, 2)::Int64, 0)::Bool, (Base.not_int)(((Base.mul_int)(d::Int64, 2)::Int64 === n@_4::Int64)::Bool)::Bool)::Bool)::Int64, 1)::Int64)::Int64, 2)::Int64)::Int64\n",
" 20: \n",
" # meta: pop location\n",
" $(Expr(:inbounds, :pop))\n",
" unless (#temp#::Int64 === 0)::Bool goto 27 # line 6:\n",
" n@_4::Int64 = (Base.checked_sdiv_int)(n@_4::Int64, 2)::Int64\n",
" goto 30\n",
" 27: # line 8:\n",
" n@_4::Int64 = (Base.add_int)((Base.mul_int)(n@_4::Int64, 3)::Int64, 1)::Int64\n",
" 30: \n",
" goto 4\n",
" 32: # line 11:\n",
" return step::Int64\n",
" end::Int64\n"
]
}
],
"source": [
"@code_warntype collatz2(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## メタプログラミング"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- マクロを使うと、コードをコードで編集できる\n",
"- `@show`や`@assert`が標準にもあるマクロ\n",
"- もちろん自分でも定義できる"
]
},
{
"cell_type": "code",
"execution_count": 173,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"@myassert (macro with 1 method)"
]
},
"execution_count": 173,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"macro myassert(ex)\n",
" msg = \"$(sprint(print, ex)) is not satisfied\"\n",
" quote\n",
" if !$(ex)\n",
" throw(AssertionError($(msg)))\n",
" end\n",
" end\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 174,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 174,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = 1"
]
},
{
"cell_type": "code",
"execution_count": 175,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"@myassert x > 0"
]
},
{
"cell_type": "code",
"execution_count": 176,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 176,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = 0"
]
},
{
"cell_type": "code",
"execution_count": 177,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "\u001b[91mAssertionError: x > 0 is not satisfied\u001b[39m",
"output_type": "error",
"traceback": [
"\u001b[91mAssertionError: x > 0 is not satisfied\u001b[39m",
"",
"Stacktrace:",
" [1] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:515\u001b[22m\u001b[22m"
]
}
],
"source": [
"@myassert x > 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"具体例: 正規表現をJuliaへコンパイル\n",
"\n",
"Automa.jlを使って、実行時のコード生成でどういうことができるかをデモンストレーションしてみる。"
]
},
{
"cell_type": "code",
"execution_count": 178,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import Automa\n",
"import Automa.RegExp: @re_str\n",
"const re = Automa.RegExp\n",
"\n",
"oct = re\"0o[0-7]+\"\n",
"dec = re\"[-+]?[0-9]+\"\n",
"hex = re\"0x[0-9A-Fa-f]+\"\n",
"prefloat = re\"[-+]?([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+)\"\n",
"float = prefloat | re.cat(prefloat | re\"[-+]?[0-9]+\", re\"[eE][-+]?[0-9]+\")\n",
"number = oct | dec | hex | float\n",
"numbers = re.cat(re.opt(number), re.rep(re\" +\" * number), re\" *\");"
]
},
{
"cell_type": "code",
"execution_count": 179,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{Symbol,1}:\n",
" :float"
]
},
"execution_count": 179,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"number.actions[:enter] = [:mark]\n",
"oct.actions[:exit] = [:oct]\n",
"dec.actions[:exit] = [:dec]\n",
"hex.actions[:exit] = [:hex]\n",
"float.actions[:exit] = [:float]"
]
},
{
"cell_type": "code",
"execution_count": 180,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"actions = Dict(\n",
" :mark => :(mark = p),\n",
" :oct => :(emit(:oct)),\n",
" :dec => :(emit(:dec)),\n",
" :hex => :(emit(:hex)),\n",
" :float => :(emit(:float)),\n",
");"
]
},
{
"cell_type": "code",
"execution_count": 181,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tokenize (generic function with 1 method)"
]
},
"execution_count": 181,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"machine = Automa.compile(numbers)\n",
"context = Automa.CodeGenContext(generator=:goto, clean=true)\n",
"@eval function tokenize(data::String)\n",
" tokens = Tuple{Symbol,String}[]\n",
" mark = 0\n",
" $(Automa.generate_init_code(context, machine))\n",
" p_end = p_eof = endof(data)\n",
" emit(kind) = push!(tokens, (kind, data[mark:p-1]))\n",
" $(Automa.generate_exec_code(context, machine, actions))\n",
" return tokens, cs == 0 ? :ok : cs < 0 ? :error : :incomplete\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 182,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6-element Array{Tuple{Symbol,String},1}:\n",
" (:dec, \"1\") \n",
" (:hex, \"0x0123BEEF\") \n",
" (:oct, \"0o754\") \n",
" (:float, \"3.14\") \n",
" (:float, \"-1e4\") \n",
" (:float, \"+6.022045e23\")"
]
},
"execution_count": 182,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokens, status = tokenize(\"1 0x0123BEEF 0o754 3.14 -1e4 +6.022045e23\")\n",
"tokens"
]
},
{
"cell_type": "code",
"execution_count": 183,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
"HTML{String}(\"\")"
]
},
"execution_count": 183,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"write(\"numbers.dot\", Automa.machine2dot(machine))\n",
"run(`dot -Tpng -o numbers.png numbers.dot`)\n",
"html\"\""
]
},
{
"cell_type": "code",
"execution_count": 184,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Tuple{Symbol,String}[], :incomplete)"
]
},
"execution_count": 184,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenize(\"0x\")"
]
},
{
"cell_type": "code",
"execution_count": 185,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Tuple{Symbol,String}[(:hex, \"0x1234\")], :ok)"
]
},
"execution_count": 185,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenize(\"0x1234\")"
]
},
{
"cell_type": "code",
"execution_count": 186,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Tuple{Symbol,String}[], :error)"
]
},
"execution_count": 186,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenize(\"0x1234G\")"
]
},
{
"cell_type": "code",
"execution_count": 187,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"quote \n",
" if p > p_end\n",
" @goto exit\n",
" end\n",
" ##722 = (Automa.SizedMemory)(data)\n",
" if cs == 1\n",
" @goto state_case_1\n",
" else \n",
" if cs == 2\n",
" @goto state_case_2\n",
" else \n",
" if cs == 3\n",
" @goto state_case_3\n",
" else \n",
" if cs == 4\n",
" @goto state_case_4\n",
" else \n",
" if cs == 5\n",
" @goto state_case_5\n",
" else \n",
" if cs == 6\n",
" @goto state_case_6\n",
" else \n",
" if cs == 7\n",
" @goto state_case_7\n",
" else \n",
" if cs == 8\n",
" @goto state_case_8\n",
" else \n",
" if cs == 9\n",
" @goto state_case_9\n",
" else \n",
" if cs == 10\n",
" @goto state_case_10\n",
" else \n",
" if cs == 11\n",
" @goto state_case_11\n",
" else \n",
" if cs == 12\n",
" @goto state_case_12\n",
" else \n",
" if cs == 13\n",
" @goto state_case_13\n",
" else \n",
" @goto exit\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" @label state_1_action_2\n",
" emit(:float)\n",
" @goto state_1\n",
" @label state_1_action_3\n",
" emit(:dec)\n",
" @goto state_1\n",
" @label state_1_action_4\n",
" emit(:hex)\n",
" @goto state_1\n",
" @label state_1_action_5\n",
" emit(:oct)\n",
" @goto state_1\n",
" @label state_1\n",
" p += 1\n",
" if p > p_end\n",
" cs = 1\n",
" @goto exit\n",
" end\n",
" @label state_case_1\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x31:0x39 || false) && true\n",
" @goto state_3_action_1\n",
" else \n",
" if (##723 in 0x2b:0x2b || (##723 in 0x2d:0x2d || false)) && true\n",
" @goto state_4_action_1\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1\n",
" else \n",
" if (##723 in 0x30:0x30 || false) && true\n",
" @goto state_2_action_1\n",
" else \n",
" if (##723 in 0x2e:0x2e || false) && true\n",
" @goto state_5_action_1\n",
" else \n",
" cs = -1\n",
" @goto exit\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" @label state_5_action_1\n",
" mark = p\n",
" @goto state_5\n",
" @label state_5\n",
" p += 1\n",
" if p > p_end\n",
" cs = 5\n",
" @goto exit\n",
" end\n",
" @label state_case_5\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_6\n",
" else \n",
" cs = -5\n",
" @goto exit\n",
" end\n",
" @label state_6\n",
" p += 1\n",
" if p > p_end\n",
" cs = 6\n",
" @goto exit\n",
" end\n",
" @label state_case_6\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_6\n",
" else \n",
" if (##723 in 0x45:0x45 || (##723 in 0x65:0x65 || false)) && true\n",
" @goto state_7\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_2\n",
" else \n",
" cs = -6\n",
" @goto exit\n",
" end\n",
" end\n",
" end\n",
" @label state_7\n",
" p += 1\n",
" if p > p_end\n",
" cs = 7\n",
" @goto exit\n",
" end\n",
" @label state_case_7\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_8\n",
" else \n",
" if (##723 in 0x2b:0x2b || (##723 in 0x2d:0x2d || false)) && true\n",
" @goto state_9\n",
" else \n",
" cs = -7\n",
" @goto exit\n",
" end\n",
" end\n",
" @label state_9\n",
" p += 1\n",
" if p > p_end\n",
" cs = 9\n",
" @goto exit\n",
" end\n",
" @label state_case_9\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_8\n",
" else \n",
" cs = -9\n",
" @goto exit\n",
" end\n",
" @label state_8\n",
" p += 1\n",
" if p > p_end\n",
" cs = 8\n",
" @goto exit\n",
" end\n",
" @label state_case_8\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_8\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_2\n",
" else \n",
" cs = -8\n",
" @goto exit\n",
" end\n",
" end\n",
" @label state_4_action_1\n",
" mark = p\n",
" @goto state_4\n",
" @label state_4\n",
" p += 1\n",
" if p > p_end\n",
" cs = 4\n",
" @goto exit\n",
" end\n",
" @label state_case_4\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_3\n",
" else \n",
" if (##723 in 0x2e:0x2e || false) && true\n",
" @goto state_5\n",
" else \n",
" cs = -4\n",
" @goto exit\n",
" end\n",
" end\n",
" @label state_3_action_1\n",
" mark = p\n",
" @goto state_3\n",
" @label state_3\n",
" p += 1\n",
" if p > p_end\n",
" cs = 3\n",
" @goto exit\n",
" end\n",
" @label state_case_3\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_3\n",
" else \n",
" if (##723 in 0x45:0x45 || (##723 in 0x65:0x65 || false)) && true\n",
" @goto state_7\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_3\n",
" else \n",
" if (##723 in 0x2e:0x2e || false) && true\n",
" @goto state_6\n",
" else \n",
" cs = -3\n",
" @goto exit\n",
" end\n",
" end\n",
" end\n",
" end\n",
" @label state_2_action_1\n",
" mark = p\n",
" @goto state_2\n",
" @label state_2\n",
" p += 1\n",
" if p > p_end\n",
" cs = 2\n",
" @goto exit\n",
" end\n",
" @label state_case_2\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || false) && true\n",
" @goto state_3\n",
" else \n",
" if (##723 in 0x45:0x45 || (##723 in 0x65:0x65 || false)) && true\n",
" @goto state_7\n",
" else \n",
" if (##723 in 0x6f:0x6f || false) && true\n",
" @goto state_10\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_3\n",
" else \n",
" if (##723 in 0x78:0x78 || false) && true\n",
" @goto state_11\n",
" else \n",
" if (##723 in 0x2e:0x2e || false) && true\n",
" @goto state_6\n",
" else \n",
" cs = -2\n",
" @goto exit\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" @label state_11\n",
" p += 1\n",
" if p > p_end\n",
" cs = 11\n",
" @goto exit\n",
" end\n",
" @label state_case_11\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || (##723 in 0x41:0x46 || (##723 in 0x61:0x66 || false))) && true\n",
" @goto state_12\n",
" else \n",
" cs = -11\n",
" @goto exit\n",
" end\n",
" @label state_12\n",
" p += 1\n",
" if p > p_end\n",
" cs = 12\n",
" @goto exit\n",
" end\n",
" @label state_case_12\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x39 || (##723 in 0x41:0x46 || (##723 in 0x61:0x66 || false))) && true\n",
" @goto state_12\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_4\n",
" else \n",
" cs = -12\n",
" @goto exit\n",
" end\n",
" end\n",
" @label state_10\n",
" p += 1\n",
" if p > p_end\n",
" cs = 10\n",
" @goto exit\n",
" end\n",
" @label state_case_10\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x37 || false) && true\n",
" @goto state_13\n",
" else \n",
" cs = -10\n",
" @goto exit\n",
" end\n",
" @label state_13\n",
" p += 1\n",
" if p > p_end\n",
" cs = 13\n",
" @goto exit\n",
" end\n",
" @label state_case_13\n",
" ##723 = (getindex)(##722, p + 0)\n",
" if (##723 in 0x30:0x37 || false) && true\n",
" @goto state_13\n",
" else \n",
" if (##723 in 0x20:0x20 || false) && true\n",
" @goto state_1_action_5\n",
" else \n",
" cs = -13\n",
" @goto exit\n",
" end\n",
" end\n",
" @label exit\n",
" if p > p_eof ≥ 0 && cs ∈ Automa.StableSet{Int64}(Automa.StableDict(1=>nothing,6=>nothing,8=>nothing,3=>nothing,2=>nothing,12=>nothing,13=>nothing))\n",
" if cs == 1\n",
" else \n",
" if cs == 6\n",
" emit(:float)\n",
" else \n",
" if cs == 8\n",
" emit(:float)\n",
" else \n",
" if cs == 3\n",
" emit(:dec)\n",
" else \n",
" if cs == 2\n",
" emit(:dec)\n",
" else \n",
" if cs == 12\n",
" emit(:hex)\n",
" else \n",
" if cs == 13\n",
" emit(:oct)\n",
" else \n",
" ()\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" end\n",
" cs = 0\n",
" end\n",
"end"
]
},
"execution_count": 187,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Automa.generate_exec_code(context, machine, actions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 今後の動向"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Juliaの人気\n",
"\n",
"TIOBE(August 2017)では46位 (https://www.tiobe.com/tiobe-index/)\n",
"- HaskellやGroovyの上\n",
"- Lua, Kotlin, Clojureよりは下\n",
"\n",
"IEEE Spectrum 2017では31位 (http://spectrum.ieee.org/static/interactive-the-top-programming-languages-2017)\n",
"- Clojure, Kotlin, Groovyより上\n",
"- Haskell, Luaより下"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Juliaの開発状況\n",
"\n",
"- Juliaの最新版はv0.6.0\n",
"- GitHubのスター数は9,000を超えた\n",
"- 600人以上がJulia本体にコントリビュート\n",
"- 過去1ヶ月で200以上のプルリクがマージされ、150以上のイシューがクローズされた\n",
"- 1500以上のパッケージ (打ち捨てられたものもあるが...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Juliaの開発体制\n",
"\n",
"[NumFOCUS](https://www.numfocus.org/)の支援プロジェクトの1つ\n",
"\n",
"\n",
"[Julia Computing Inc.](https://juliacomputing.com/)というJuliaの開発者達による企業が作られた\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Julia 1.0?\n",
"\n",
"- まだ未定だが、運が良ければ今年か、来年に出る?\n",
"- Juliaのリリースは毎回半年ぐらい遅れるので、多分来年の上旬くらいか\n",
"- Julia 1.0が出れば、とりあえず数年は安定して使えそう\n",
"\n",
"入りそうな機能\n",
"- Pkg3: パッケージシステムのメジャーアップデート\n",
" - 現在のPkg2がデカいレポジトリをガンガン書き換えながら管理するので色々問題が\n",
" - Pkg2では、パッケージのバージョンを固定した環境などが作りにくい\n",
" - Pkg3では、分散管理・TOMLによるバージョン固定など使いやすくなる予定\n",
" - https://github.com/JuliaLang/Juleps/blob/master/Pkg3.md\n",
"- `NamedTuple`: 名前付きタプル\n",
" - Juliaの`Tuple`は位置(1,2,...)で要素を指定\n",
" - `NamedTuple`は名前でも要素を指定できるように\n",
" - `(foo=1.0, bar=\"hoge\")`のような構文も追加される\n",
" - https://github.com/JuliaLang/julia/pull/22194\n",
"- `Null`値: 欠損値の扱いの向上\n",
" - 現在`Nullable`でnullかもしれない値を表現\n",
" - 配列とかに入れるとちょっと面倒 (いちいち`Nullable`を外さないといけない)\n",
" - `Union{Float32,Void}`みたいなのが高速に扱えるようになる\n",
" - https://github.com/JuliaLang/julia/pull/22441 (マージ済み)\n",
"- Parallel Task Runtime: マルチスレッド機能の本気実装\n",
" - Juliaの同時実行できるタスクは1つだけ\n",
" - `@threads`を使えばforループを局所的に並列実行できるが...\n",
" - タスクを別スレッドで並列実行できるようになりそう\n",
" - https://github.com/JuliaLang/julia/pull/22631"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# (おまけ) 作ったパッケージの紹介"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"全部or大半のコードを書いた公式パッケージ\n",
"\n",
"- [TranscodingStreams.jl](https://github.com/bicycle1885/TranscodingStreams.jl)\n",
"- [CodecZlib.jl](https://github.com/bicycle1885/CodecZlib.jl)\n",
"- [CodecBzip2.jl](https://github.com/bicycle1885/CodecBzip2.jl)\n",
"- [CodecXz.jl](https://github.com/bicycle1885/CodecXz.jl)\n",
"- [CodecZstd.jl](https://github.com/bicycle1885/CodecZstd.jl)\n",
"- [CodecBase.jl](https://github.com/bicycle1885/CodecBase.jl)\n",
"- [EzXML.jl](https://github.com/bicycle1885/EzXML.jl)\n",
"- [DocOpt.jl](https://github.com/docopt/DocOpt.jl)\n",
"- [Snappy.jl](https://github.com/bicycle1885/Snappy.jl)\n",
"- [BioCore.jl](https://github.com/BioJulia/BioCore.jl)\n",
"- [BioSymbols.jl](https://github.com/BioJulia/BioSymbols.jl)\n",
"- [BioSequences.jl](https://github.com/BioJulia/BioSequences.jl)\n",
"- [BioAlignments.jl](https://github.com/BioJulia/BioAlignments.jl)\n",
"- [GenomicFeatures.jl](https://github.com/BioJulia/GenomicFeatures.jl)\n",
"- [BGZFStreams.jl](https://github.com/BioJulia/BGZFStreams.jl)\n",
"- [Automa.jl](https://github.com/BioJulia/Automa.jl)\n",
"- [IndexableBitVectors.jl](https://github.com/BioJulia/IndexableBitVectors.jl)\n",
"- [FMIndexes.jl](https://github.com/BioJulia/FMIndexes.jl)"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Julia 0.6.0",
"language": "julia",
"name": "julia-0.6"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.6.0"
},
"nbpresent": {
"slides": {
"0c6a42d0-560d-4400-875d-c7063bb04e15": {
"id": "0c6a42d0-560d-4400-875d-c7063bb04e15",
"prev": "4cf4bb21-c3c8-48c5-bcf4-b63ec5bb5997",
"regions": {
"3e96ccd7-3541-4750-b4e4-76ae05591bce": {
"attrs": {
"height": 0.8,
"width": 0.8,
"x": 0.1,
"y": 0.1
},
"content": {
"cell": "385e0a13-6529-48cc-8a68-5401cb5e11ed",
"part": "whole"
},
"id": "3e96ccd7-3541-4750-b4e4-76ae05591bce"
}
}
},
"4129f5d0-78d8-424e-ad72-0775ccbbdc53": {
"id": "4129f5d0-78d8-424e-ad72-0775ccbbdc53",
"prev": "0c6a42d0-560d-4400-875d-c7063bb04e15",
"regions": {
"94eb76a6-811b-4535-81b1-118d4df52e5b": {
"attrs": {
"height": 0.8,
"width": 0.8,
"x": 0.1,
"y": 0.1
},
"content": {
"cell": "c825d089-a85d-4f52-9b30-88f6e5f6ce3b",
"part": "whole"
},
"id": "94eb76a6-811b-4535-81b1-118d4df52e5b"
}
}
},
"4cf4bb21-c3c8-48c5-bcf4-b63ec5bb5997": {
"id": "4cf4bb21-c3c8-48c5-bcf4-b63ec5bb5997",
"prev": null,
"regions": {
"a0a1cbdb-6666-42af-bd4c-2ecaf9fcb641": {
"attrs": {
"height": 0.8,
"width": 0.8,
"x": 0.1,
"y": 0.1
},
"content": {
"cell": "d8145165-8d8e-4c7d-8511-710cae0113ed",
"part": "whole"
},
"id": "a0a1cbdb-6666-42af-bd4c-2ecaf9fcb641"
}
}
},
"f92d0851-8379-4d31-9d41-1ac5342d070d": {
"id": "f92d0851-8379-4d31-9d41-1ac5342d070d",
"prev": "4129f5d0-78d8-424e-ad72-0775ccbbdc53",
"regions": {
"3371c62e-213a-4c56-88f9-781a4da9aa52": {
"attrs": {
"height": 0.8,
"width": 0.8,
"x": 0.1,
"y": 0.1
},
"content": {
"cell": "2a494f69-3536-4096-bfc1-32ebdc500a86",
"part": "whole"
},
"id": "3371c62e-213a-4c56-88f9-781a4da9aa52"
}
}
}
},
"themes": {}
},
"toc": {
"colors": {
"hover_highlight": "#DAA520",
"navigate_num": "#000000",
"navigate_text": "#333333",
"running_highlight": "#FF0000",
"selected_highlight": "#FFD700",
"sidebar_border": "#EEEEEE",
"wrapper_background": "#FFFFFF"
},
"moveMenuLeft": true,
"nav_menu": {
"height": "84px",
"width": "252px"
},
"navigate_menu": true,
"number_sections": false,
"sideBar": true,
"threshold": 4,
"toc_cell": false,
"toc_position": {
"height": "710px",
"left": "0px",
"right": "1068px",
"top": "32px",
"width": "212px"
},
"toc_section_display": "block",
"toc_window_display": true,
"widenNotebook": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}