Julia Language
高次関数
サーチ…
構文
- foreach(f、xs)
- マップ(f、xs)
- フィルタ(f、xs)
- reduce(f、v0、xs)
- foldl(f、v0、xs)
- foldr(f、v0、xs)
備考
関数はパラメータとして受け付けることができ、戻り型として生成することもできます。実際、関数は他の関数の本体の内部に作成することができます。これらの内部関数はクロージャーとして知られています。
引数としての機能
関数はJuliaのオブジェクトです。他のオブジェクトと同様に、それらを引数として他の関数に渡すことができます。関数を受け入れる関数は高次関数と呼ばれます。
例えば、標準ライブラリのforeach
関数を、最初のパラメータとして関数f
を取ることによって実現することができます。
function myforeach(f, xs)
for x in xs
f(x)
end
end
この関数が実際に期待どおりに機能することをテストできます:
julia> myforeach(println, ["a", "b", "c"])
a
b
c
関数を最初のパラメータとして、後のパラメータではなく、Juliaのdoブロック構文を使用することができます。 doブロックの構文は、関数の最初の引数として無名関数を渡すのに便利な方法です。
julia> myforeach([1, 2, 3]) do x
println(x^x)
end
1
4
27
上記myforeach
実装は、組み込みのforeach
関数とほぼ同じです。他にも多くのビルトイン高次関数が存在します。
高次関数は非常に強力です。場合によっては、高次関数を扱うときに実行される正確な演算が重要でなくなり、プログラムが抽象的になることがあります。 結合子は、抽象的な高次関数のシステムの例です。
マップ、フィルター、および縮小
標準ライブラリに含まれる最も基本的な高次関数のうちの2つは、 map
とfilter
です。これらの関数は汎用であり、任意の反復可能関数で操作できます。特に、 配列の計算に適しています 。
学校のデータセットがあるとします。各学校は特定の科目を教え、クラス数、平均クラス人数を教えています。次の不変型の学校をモデル化できます。
immutable School
subject::Symbol
nclasses::Int
nstudents::Int # average no. of students per class
end
私たちの学校のデータセットはVector{School}
です。
dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]
私たちが合計で数学のプログラムに登録されている学生の数を見たいとします。これを行うには、いくつかの手順が必要です。
- データセットを数学(
filter
)を教える学校に限定する必要がありfilter
- 各学校の生徒数を計算する必要があり
map
(map
) - その数の学生数を1つの値に減らす必要があります。合計(
reduce
)
純粋ではない(最もパフォーマンスの高いものではない)ソリューションは、単にこれらの3つの高次関数を直接使用することです。
function nmath(data)
maths = filter(x -> x.subject === :math, data)
students = map(x -> x.nclasses * x.nstudents, maths)
reduce(+, 0, students)
end
私たちのデータセットに190人の数学の学生がいることを確認します:
julia> nmath(dataset)
190
これらの機能を組み合わせてパフォーマンスを向上させる機能があります。たとえば、 mapreduce
関数を使用してマッピングと縮小を1ステップで実行すると、時間とメモリが節約できます。
reduce
は、 +
ような連想操作にのみ意味がありますが、非連想操作で縮小を実行すると便利なことがあります。高次関数foldl
およびfoldr
は、特定の縮小順序を強制するために提供されます。