#Julia言語

既存の型A, B, Cの組み合わせにメソッドfを追加したければ

function f(a::A, b::B, c::C) ~ end

とすればよい。

すでに名前 f が使われていても、モジュールで名前空間を区切れば問題無し。
#Julia言語 既存のモジュールFooで定義されている函数Foo.fをA, B, Cの型の組み合わせに新たに作用させたければ

function Foo.f(a::A, b::B, c::C) ~ end

とすればよい。

A, B, Cのどれかが自分で定義した型なら、モジュールFooで定義済みのFoo.fの機能はそのまま温存される。
#Julia言語 以上のように、Juliaの多重ディスパッチならば、

①他人が定義した型の組み合わせに、自分が欲しいメソッドを自由に追加できる。

②他人が定義した函数を、自分が定義した(ものを含む)型の組み合わせに自由に作用させることもできる。

他人の仕事を自分の仕事で流用するのが容易。
#Julia言語 ②にあたることは所謂OOPでの常套手段。そのとき問題になるのは①の側で、②を享受できるメリットを潰さずに、①も享受できるようにしたい。

その1つの答えがJuliaの多重ディスパッチであるというような話が以下のリンク先にあります。去年の12月。結構最近。

discourse.julialang.org/t/is-julias-wa…
#Julia言語 他人が書いたコードを自分が利用するときには

①他人が作った型A,B,Cに関する

function f(a::A, b::B, c::C) ~ end

②Foo.f(a, b, c)は他人が作った函数で、A,B,Cのどれかが自分が作った型のときの

function Foo.f(a::A, b::B, c::C) ~ end

のパターンがある。シンプルで覚え易い。
#Julia言語 の末端ユーザー的に(やろうと思えばできるが(以前解説した))、やめて欲しいことは、f(a,b,c)の最初の引数を特別扱いして、a.f(b,c)と書くスタイルをJulia界で広めること。

せっかく、f(a,b,c)のa,b,cについて平等に多重ディスパッチされる状況が便利なのに対称性を崩されるのは辛い。
#Julia言語 例えば、標準基底 e(i) と行列Aについて、LinearAlgebra. dot(e(i), A, e(j)) はA[i,j]になるのですが、e(i)に特別な型CanBasisを与えて、

LinearAlgebra. dot(x::CanBasis, A::AbstractMatrix, y::CanBasis) = A[x.i, y.i]

のように定義できて爆速dotの標準基底を実現できます。続く
#Julia言語 LinearAlgebra. dot(x, A, y) を使っている他人が書いたコードでも、私が作ったCanBasisオブジェクトは機能してくれる。

これは上の②のパターン。

既存の型の組み合わせに自分で自分用の函数を定義する①のパターンはもっとありふれている。
#Julia言語 「タブ補完」の問題については以下のリンク先のプルリクエストを参照。
github.com/JuliaLang/juli…
#Julia言語 以下のリンク先の発言は、(数値)線形代数の実装を効率化するためには、シングルディスパッチのOOPスタイルでは無理で、Juliaスタイルの計算効率を上げるスタイルの多重ディスパッチが必要なのではないかという意見。

Juliaには対称三重対角行列の型もある(笑)

discourse.julialang.org/t/is-julias-wa…
#Julia言語 以下のリンク先の発言にあるリスト

①特殊な行列の間の二項演算の効率的な実装には二重ディスパッチが有用。

②異なる型の数値の間の演算。以前私も解説して、最近もどこかで話題になったpromotionの話。

③文脈依存での各種オブジェクトの表示

discourse.julialang.org/t/is-julias-wa…
#Julia言語 以下のリンク先には、多重ディスパッチの少なくとも3つあるキラーユースケースで最も重要なのが線形代数だと書いてあった!

私が職業的にJuliaについて最も感心したのは線形代数の実装の仕方。一般ユーザー側からはまるで線形代数の教科書通りに見える。

discourse.julialang.org/t/why-specify-…
#Julia言語 上の続き。Juliaでは安全のために型を使うのではないとも書いてあった。「静的型付けで安全を確保」教の信者がJuliaで困るのは当たり前。

単なる数学的仕組みに過ぎないものについて、特定の使用法だけしか思いつかないように誘導されていることに気付いたら、すぐに逃げるべき。
#Julia言語 もちろん、そこではJET.jlも引用されている。

discourse.julialang.org/t/why-specify-…

JET.jl↓
github.com/aviatesk/JET.jl
#Julia言語

C++の開発で知られるBjarne Stroustrupさんは、f(x,y)の最初の引数を特別扱いしてx.f(y)と書くスタイルをろくでもないものとした上で、「浅い理解」だが「ひどくファッショナブル」でしたと言っているんですね。

discourse.julialang.org/t/is-julias-wa…

open-std.org/jtc1/sc22/wg21…
#Julia言語

「Juliaではたとえコミュ障でも他人が作ったパッケージの機能を自分のコードで利用できる仕組みになっている」とまとめられる感じ?

discourse.julialang.org/t/is-julias-wa…
#Julia言語

多重ディスパッチの仕組みのみを使ったtraitの実現(いわゆるHoly trait)は、ほぼ「何でもあり」になる仕組み。

そういうより一般的で高機能な仕組みを使って「インターフェース」が実現できて何が悪いのか、私も理解できなかった。

discourse.julialang.org/t/is-julias-wa…
#Julia言語 Foo{T, U} のようなパラメトリック型に関してよく使われているコードのパターン↓
docs.julialang.org/en/v1/manual/m…

型昇格の話
docs.julialang.org/en/v1/manual/m…



所謂Holy traiteの話(trait-based dispatch)
docs.julialang.org/en/v1/manual/m…

もそこにある。
#Julia言語 添付画像の 1 Python の例は

discourse.julialang.org/t/is-julias-wa…

より

Pythonだと

from fractions import Fraction
Fraction(1, 10) * 1j + Fraction(2, 10) * 1j
→0.30000000000000004j

Juliaなら

1//10 * 1im + 2//10 * 1im
→0//1 + 3//10*im

この辺はJuliaスタイルの良い点。
#Julia言語

2//10 は Rational{Int64} 型
1im は Complex{Int64} 型

2//10 * 1im の型はそれらの型の組み合わせの昇格先である Complex{Rational{Int64}} になる。

この辺の処理は多重ディスパッチではやりやすい。

x * y の処理の仕方はxとyの型の昇格で決まる。

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with 黒木玄 Gen Kuroki

黒木玄 Gen Kuroki Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @genkuroki

25 Mar
#数楽

多項式f∈ℝ[x]に「a∈ℝをf(a)∈ℝを対応させる函数」を対応させる写像は単射なので、多項式fとそれに対応する実数の函数を区別しなくも大丈夫。(無限体でもOK)

有限体F上の多項式g∈F[x]に「a∈Fをg(a)∈Fを対応させる函数」を対応させる写像は単射でないので、それらを同一視できない。
#数楽 例えば二元体𝔽₂={0,1} (1+1=0)について、𝔽₂上の多項式としてxとx²は異なるが、𝔽₂上の函数としてはどちらも恒等写像になって等しくなってしまう。

xとx²を𝔽₂の2次拡大𝔽₄=𝔽₂[α] (α²=α+1)上の函数とみなしたものは互いに異なる。

こういう具体例がノータイムで出て来ることが大事。
#数楽 面倒なのは有理函数(多項式環の分数体の要素)に対応する「函数」の場合。

有理函数ごとに定義域も変わるので、異なる定義域を持つ函数達を同時に扱うための「処理」が必要になる。(これには複数の処方箋がある。)

結果的に、無限体の場合には、有理函数と対応する「函数」は同一視可能になる。
Read 7 tweets
25 Mar
大学生相手であっても、必要な数学の実力は結構高いので、統計学を教えるのに苦労しています。

高校生相手に検定が「お墨付きが得られる道具」であるかのように教えられてしまうようになったら最悪。

あと、信頼区間がモデル依存であることも(大学生と同様に)教えることにならないと思う。
現実には世界的にかなり悲惨なことになっていて、論文を日常的に書いている研究者であっても、統計的検定を「お墨付きが得られる道具」扱いしている人達が沢山いるんじゃないか?

そういう現状は若くて優れた研究者が育つことを妨害していると思う。

こういう問題を維持固定しないような教育が必要。
まだ高校生なのに、「統計的に有意である!」を水戸黄門的な「ひかえおろう!」と同じ意味で使うようになったら最悪(笑)
Read 24 tweets
25 Mar
#Julia言語 リポジトリの方の公式マニュアルに以下が追加されましたね。

* 引数の型の過剰な制限はよくある間違いです。疑わしいなら引数の型を書くのをやめましょう。

* Juliaでは戻り値の型宣言はほとんど使われません。一般に「型安定」な函数を書くべきです。

github.com/JuliaLang/juli… Image
#Julia言語 具体的には

fib(n::Int) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)

はよくある間違で、

fib(n)::Int = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)

も誤りです。どちらでもBigIntによる計算が不可能になる。よく分からないなら

fib(n) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)

でよい。
#Julia言語 無用に引数の型を制限してしまううようだと、NASAでは仕事をできなくなります。(NASAでもJuliaを使っている)
Read 11 tweets
24 Mar
#Julia言語 (1-2^(1-s))ζ(s) は交代級数になりEuler変換が使える。Euler変換を使えば数十項でFloat64の精度を使い切った計算が可能。

①オイラー変換のウェイトのグラフ
②64項の和の計算結果
③正確な値との相対誤差の常用対数、横軸Lは項数

Euler変換はかなり強力。

nbviewer.jupyter.org/gist/genkuroki… ImageImageImage
#Julia言語 Euler変換とは、1つ前のツイートの1つ目の添付画像で示された謎のウェイト w^{(L)}_k をかけて (-1)^k a_k を k=0からL-1まで足し上げると、(-1)^k a_k のk=0から∞までの和の良い近似になるという魔法のような話。

1つ前のツイートのLは2^6=64.
#Julia言語 #数楽 (1-2^(1-s))ζ(s) のEuler変換は複素平面全体で収束するので、ζ(s)の近似計算にも使える。

効率はそんなに良くないが、リーマン予想の数値的確認や視覚化をそれで行うこともできる。

非自明な零点の周囲のプロットもオイラー変換を知っていれば容易に可能である。
Read 4 tweets
24 Mar
#Julia言語 もう何度目になるか分かりませんが、私もdual numbersを実装してみた。

添付画像2の @ code_warntype と @ btime の結果に注目。この2つの確認は必ずやった方がよい。続く

ソースコード↓
nbviewer.jupyter.org/gist/genkuroki… ImageImageImageImage
#Julia言語 自動微分の仕組みのdual numberパートは易しい部分。

難しいのは大量の函数を合成してできる函数の微分をどのように効率的に求めるか。

行列A,B,C,Dのサイズによって、A(B(CD))と((AB)C)Dで計算にかかる時間が大きく違う場合がある(そのことは行列の積の定義さえ知っていれば理解可能)。
#Julia言語 Juliaで積極的に計算を遅くするには、

① グローバル変数の値を引数を経由せずに函数の中で中で使う。

② structを

struct Foo
a
b
end

のように定義して使う。もしくはこれのバリエーション。

あとほとんどの場合に mutable struct は必要ない。
Read 8 tweets
24 Mar
悪ふざけ論文のネタ:

* f(a,b,c,…)の中の個人aを特別扱いして、a.f(b,c,…) のように書き、函数fをaの所有物とするアイデアは極めて資本主義的。

* それに対抗する解放運動として多重ディスパッチが提案されて来たが、ことごとく資本主義に敗北して来た。

* 解放運動にとってJuliaは(略)
上のツイートはネタ(冗談)なので要注意。
axiom of equality を「平等の公理」だと誤解させて(本当は「等号の公理」)、さらに axiom of choice を「(産むか産まないかの)選択(を認める)公理」と読ませることに成功したパロディ論文は有名。
physics.nyu.edu/faculty/sokal/…

他にも滅茶苦茶で笑えるのですが、アクセプトされて大騒ぎになった。
Read 4 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!