#Julia言語 では任意の型のオブジェクトfにf(x), f(x,y), …のように使える函数の機能を追加できます。

だから、函数を引数とする函数φを function φ(f::Function) ~ end と定義すると、見た目的に動いて欲しいコードが動かなくなるリスクが増える。

function φ(f) ~ end と書くべき。
#Julia言語 函数を中身に持つstructを

struct Foo{T<:Function}
f::T
end

と作っても、見た目的に動いて欲しいコードが動かなくなる場合が増えます。

struct Foo{T}
f::T
end

なら大丈夫。

Juliaの型について理解が不十分な状態で型名をコード中に書くと大抵失敗する。
#Julia言語 Juliaでは、型が先にあってその中に値が含まれていると考えるのではなく、値が先にあって、その値の具体的な型を次に考え、その後にその具体的な型を含むもっと広い抽象型を考える、という順番に考えないといけない感じ。

Juliaでのコンパイルは入力の値の具体型に合わせて実行される。
#Julia言語 型名を書いたせいで、見た目的に動いて欲しいコードが動かなくなる他の場合に、

function f(v::AbstractVector) ~ end

があります。

例えば、g = (k^2 for k in 1:10) はBase.Generator型になり、AbstractVector型にならないので、f(g)とはできなくなる。
#Julia言語 そういう問題があることを理解した上で受け入れていれば、function f(v::AbstractVector) ~ end で全然問題ない。

しかし、理解が伴っていないと、動いて欲しいコードが動かずに悩むことになる。

function f(v) ~ end と型名を書かずに済ませることができるなら安全。
#Julia言語 引数の型の違いによる(多重)ディスパッチ(同名函数の違う動作)を利用したい場合には、function f(v) ~ end ではなく、function f(v::AbstractVector) ~ end のように書く必要がある。

一方、多重ディスパッチを使わない場合には、function f(v) ~ end と引数vの型を書かない方が安全。
#Julia言語 計算効率を上げるための最適化にときに、函数の引数の型を書いていたせいで、正常に動いているコードが動かなくなることが何回かありました。

最適化のために@ viewマクロを追加した途端に動かなくなったこともあった(笑) その原因は function f(x::Array) ~ end
#Julia言語 型の違いによるディスパッチの例

double(x) = 2x # fallback
double(x::AbstractString) = x^2

double(3)
→ 6

double("hoge")
→ "hogehoge"

s = @ view "hoge"[2:end]
→ "oge" (SubString型)

double(s)
→ "ogeoge"
#Julia言語 上で double(x::AbstractString) = x^2 を

double(x::String) = x^2

としてしまっていると

s = @ view "hoge"[2:end]
→ "oge" (SubString型)

double(s)

Error: ~ no method matching double(::SubString{String})
Closest candidates are:
double(::String) at ~

となる。

• • •

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

23 Mar
#Julia言語

DifferentialEquations.jl のシンプルな使用例

nbviewer.jupyter.org/gist/genkuroki…
単振子

初期条件は一回転せずにすむぎりぎりの速さで揺らすこと。振子が倒立直前の状態前で行く。

この場合の運動方程式は数値的に解くのに失敗し易いので、各数値解法のテストに使えます。

添付画像→厳密解 Image
#Julia言語

ODEProblemのデフォルトのソルバの場合

橙破線の厳密解から大幅にずれている。

正方向に倒立直前状態まで回転して、負方向に倒立直前まで行く所までは正確だが、そこから先はめちゃくちゃ。

エネルギーも全然保存されない。

これを見れば数値計算は要注意であることがよく分かる。 Image
#Julia言語

Tsitouras' Runge-Kutta-Oliver 6 stage 5th order method で時刻の刻み幅が dt = 0.05 の場合

これは概ね正確。エネルギー保存則の側がちと不安な動き方。

DifferentialEquations.jlでは膨大な数のソルバが実装されています。
diffeq.sciml.ai/stable/solvers… Image
Read 18 tweets
23 Mar
#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の多重ディスパッチならば、

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

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

他人の仕事を自分の仕事で流用するのが容易。
Read 17 tweets
22 Mar
#Julia言語

Juliaでは入力の値の具体的な型を見てからそれに合わせてネイティブコードにコンパイルする仕組みで、支払わなければいけないトレードオフは当然発生する。

しかし、入力の値の型ごとに最適化されたネイティブコードに自動的にコンパイルされる仕組みは多くの場合に便利です。
#Julia言語

Juliaで函数f(x)のコードを書くときには、単純に

f:A→B

のようになるとは考えずに

xの値の具体的な型が決まると、xの値の具体的な型が伝搬して行って、f(x)の値の具体的な型も決まる

となるようにコードを書くことを考えます。

確認には @ code_warntype などを使う。
Read 5 tweets
22 Mar
#Julia言語 普通にJuliaの(野良または公式)パッケージ化した方がよいかも。(Juliaなら野良パッケージ作成は相当に簡単)

ただしその場合にはパッケージ名に"Julia"も文字列は入れない方がよい。
pkgdocs.julialang.org/v1/creating-pa…

野良及び公式パッケージ作成の基本→ github.com/invenia/PkgTem…
#Julia言語 PkgTemplates.jlについて巷に出回っている解説で注意するべきことは、GitHubでmasterではなくmainを使うようになったこと。

masterと書いてあったらmainと解釈しなければいけない。注意しないと、mainブランチと別にmasterブランチを作ることになってしまう。

(((私は実際にやらかした)))
#Julia言語 自分のパソコン内にしかないパッケージをJuliaで作るのは非常に簡単。適切なディレクトリで

pkg> generate MyFoo
pkg> dev MyFoo
julia> using Revise
julia> using MyFoo
julia> MyFoo.greet()
MyFoo/src/MyFoo.jl内のgreet()の内容を変更
自動的にREPLに反映
julia> MyFoo.greet()
Read 5 tweets
21 Mar
#Julia言語 10行では無理なやつ

正方形上の自由境界条件の波動方程式の離散化をDifferentialEquations.jlで数値的に解いて動画を作ってみた↓
nbviewer.jupyter.org/gist/genkuroki…

これを作るために必要な行数は40行程度でした。
#Julia言語 約1万個の質点がバネで繋がっている状況を記述する常微分方程式 prob を DifferentialEquations.jl に sol = solve(prob) の形式で数値的に解かせています。自分でソルバを書かなくて良いとかなり楽です。

nbviewer.jupyter.org/gist/genkuroki…
#Julia言語 正方形ではなく、正五角形上の自由境界条件のもとでの波動方程式の数値解。

これもDifferentialEquations.jlを使っています。
コードの効率はそうよくないのですが、シンプル。
Read 46 tweets
20 Mar
私が大学1年で受けたコンピュータの教育はFORTRAN 77で、最初の講義でホーナー法の解説があった。

FORTRAN 77でも教えられることばかりだとつまらないので、数値計算におけるコードの自動生成の重要性なんかも教育に組み入れると面白いと思う。

#Julia言語 なら完全なマクロがある。
#Julia言語 Juliaでも使われているFloat64でのsin(x), |x|≤π/4をよく近似する13次多項式と同等の13次多項式をJuliaを使って自力で求めてみる話が以下のリンク先スレッドにあります。

Float64に特化した係数の計算は繊細な注意が必要な問題だった。

興味がある人は自分でやってみるとよいと思う。
#Julia言語 私が求めた13次多項式の係数と伝統的に使われている13次多項式の係数は微小に違うのですが、相対誤差をほぼ同じです。グラフ的には区別ができない!

謎のレシピを謎のまま残さずに自力で求められるようにしておくことが、数学がらみの事柄では基本になります。

gist.github.com/genkuroki/362b…
Read 5 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!