関数とメソッド

Juliaのマニュアルの目次は以下のようになっています(括弧内は丸井綜研訳)。

  1. Introduction (はじめに)
  2. Getting Started (動かしてみよう)
  3. Integers and Floating-Point Numbers (整数と浮動小数)
  4. Mathematical Operations (数学演算)
  5. Complex and Rational Numbers (複素数有理数)
  6. Strings (文字列)
  7. Functions (関数)
  8. Control Flow (制御構造)
  9. Variables and Scoping (変数とスコープ)
  10. Types (型)
  11. Methods (メソッド)
  12. Constructors (コンストラクタ)
  13. Conversion and Promotion (変換と昇格)
  14. Arrays (配列)
  15. Running External Programs (外部プログラムの実行)
  16. Metaprogramming (メタプログラミング)
  17. Parallel Computing (並列計算)
  18. Calling C and Fortran Code (CとFortranのコードを呼び出す)
  19. Standard Library Reference (標準ライブラリリファレンス)
  20. Potential Features (予定される機能)
  21. Performance Tips (パフォーマンス向上のために)

ここで「ん?」と思ったのは関数とメソッドがそれぞれ別の章を与えられていること。僕のこれまで使ってきた言語の知識からの直感では、クラスに属さないのが関数で、クラスに属すのがメソッドかなぁとも思いましたが、実は違うのでした。

Juliaにおいては、関数は「引数の型が定められていない」もので、メソッドは「引数の型が定められている」もののようです。

たとえば、ふたつの整数の2乗和を計算する関数を定義してみましょう。

julia> nijouwa(x::Int64, y::Int64) = x*x + y*y

julia> nijouwa(3, 4)
25

今のところこの関数には「64ビット整数の2乗和を計算する」機能しかありません。そのため、浮動小数点数の2乗和を計算しようとするとエラーが出てしまいます。

julia> nijouwa(3.0, 4.0)
no method nijouwa(Float64,Float64)

そこで、浮動小数点数についての2乗和も定義します。

julia> nijouwa(x::Float, y::Float) = x*x + y*y

julia> nijouwa(3.0, 4.0)
25.0

ここでnijouwaは「整数の2乗和」と「浮動小数点数の2乗和」というふたつのメソッドをもつ関数になりました。以下のようにプロンプトで関数名を打ち込めば調べることができます。

julia> nijouwa
Methods for generic function nijouwa
nijouwa(Int64,Int64) at prompt:1
nijouwa(Float,Float) at prompt:1

nijouwaを定義するときには+を使いましたが、じつはこの+も多くのメソッドを持つ関数なのでした。

julia> +
Methods for generic function +
+(Real,Range{T<:Real}) at /Users/marui/julia/j/range.j:122
+(Real,Range1{T<:Real}) at /Users/marui/julia/j/range.j:123
+(Ranges{T<:Real},Real) at /Users/marui/julia/j/range.j:124
・
・
・

引数の数が違うメソッドも同じように定義できますし、引数に型を指定しなければAny型が使われるので、呼び出し時に(nijouwaの中の+の呼び出し時に、+が持つ多くのメソッドから)最適な型が選ばれることになります。

julia> nijouwa(x,y,z) = x*x + y*y + z*z

julia> nijouwa
Methods for generic function nijouwa
nijouwa(Int64,Int64) at prompt:1
nijouwa(Float,Float) at prompt:1
nijouwa(Any,Any,Any) at prompt:2