俺のための Julia 入門(3)関数

Julia
俺のためのJulia入門
Author

司馬 博文

Published

9/08/2020

概要
Julia において,関数はメソッドの貼り合わせである.スクリプト言語のように,気軽に関数定義を行うこともできれば(単一メソッドによる関数と解す),多重ディスパッチによる実装も可能である.

1 関数定義

  1. 複数行記述

    function name(arg, [arg2, ])
        methods
    end
  2. 1行記述:極めて数学的に直感的な定義法

    name(arg, [arg2, ]) = return_value
  3. 型の明示

    name(arg::DataType, [arg2::DataType, ])::DataType = return_value
  • 型の指定は全て任意.
  • 戻り値にも型を指定した場合は,暗黙のうちにそれに変換して返される.変換できない場合はERROE: InexactError

1.1 返り値について

  • returnの省略
    • 戻り値がreturn文で指定されなかった場合は,endの直前の1行で評価された値が自動的に返り値となる.
  • returnとだけ書くと,return nothingの略記とみなす.
  • 複数返り値
    • tupleを返せば良い.

1.2 引数について

  • 可変長引数
    • … objectを用いてarg…またはarg::DataType…とすれば,tuple型で受け取れる.
    • 受け取ったargに対してlnegth(arg)としてforを回せる.
    • 関数の最後の引数のみに定義可能.
  • optional引数
    • name=valueとして宣言すると,optionalになる.
    • 全てのoptional引数は,そうでない引数より前に来ることができない.
    • positionalである.あまりに多い場合はkeyword引数にすると良い.
  • keyword引数
    • optional引数の記法において,コンマ”,”の代わりにセミコロン”;”で区切ると,以降は名前付きで呼び出さなきゃいけないkeyword引数となる.
    • 呼び出すときはコンマ”,”で良い.
    • 名前付きで呼び出せるので
  • 多重ディスパッチ
    • 引数の型注釈が違えば,同じ名前の関数をいくつも定義できる.
    • 呼ぶ時はJuliaが暗黙のうちに正しいものを呼んでくれる.

1.3 匿名関数:->

->がconstructorで,大体代入してから使う.map, filter 関数の引数として用いられる.

  1. 1行記述 name = arg -> value 左辺のnameは関数objectに,右辺は匿名関数である.
  2. 複数行記述 name = arg -> begin suite end
  • データ型はvar”#1#2”となる.なぜだ?

2 メソッド

2.1 導入

+など,Julia における関数 (generic function) はメソッドの貼り合わせとして実装される.1

first(methods(+), 5)
5-element Vector{Method}:

Thus, the overall behavior of a function is a patchwork of the behaviors of its various method definitions.
Docs.

関数が呼び出された際に,どのメソッドを実行するかの選択機構を ディスパッチ という.2 Julia は引数の型だけでなく,引数の数も見てディスパッチを行う.従来のように,最初の引数の型を見るディスパッチと区別して,これを 多重ディスパッチ という.3

ここでは,今までの関数定義とは違い,:: signature による明示的な型制約を設けた定義が行われる.

2.2 パラメトリックメソッド

same_type(x::T, y::T) where {T} = true
same_type(x,y) = false
same_type(1, 2.0)
same_type(1, 2)
methods(same_type)
# 2 methods for generic function same_type from Main:
  • same_type(x::T, y::T) where T in Main at In[3]:1
  • same_type(x, y) in Main at In[3]:2

T は返り値としても使える:

mytypeof(x::T) where {T} = T
mytypeof(nothing)
Nothing

2.3 呼び出し可能オブジェクト

3 組み込み関数

3.1 Base.

  • nextind(str::AbstractString, i::Integer, n::Integer=1) -> n-th_index::Int

    • n==1の時,iでindexされているstrの要素の,次の要素の開始indexの値を返す.
    • n>1の時,n個次の要素の開始indexの値を返す.
    • n==0の時,iでindexされているstrの要素が存在する場合,iを返す.
  • prevind()

  • rand([rng=GLOBAL_RNG], [S=Float64], [dims…]) ->

    • 可変長引数dimをとって,(n,m,…)だとn×m×…のランダム行列を返す.
  • map(f, c…) -> collection

    • collection型であるcの各要素にfを施す.
    • 積写像である.
  • filter(f,a) -> a’

    • aはcollection, fは真理値関数.
    • collection aのcopyであって,fがfalseと判定したものを返す.

3.1.1 Base.Iterators.

  • enumerate(iter) -> (i,x)::iterator
    • iは1から始まるindex,xはiterのi番目の要素.
    • iterable object xだけで無く,カウンターiも同時に得られるところが便利.それに常にx = iter[i]とは限らない.
      • この返り値objectの型はBase.Iterators.Enumerate{NTuple{n,T}}.

3.1.2 Base.MainInclude.

  • eval(expr)
    • Evaluate an expression in the global scope of the containing module.

3.2 Core.

  • eval(m::Module, expr)
  • isa(x, type) —> Bool
    • 中置記法(infix)でx isa typeともかける.
    • xがtypeのinstandeならtrueを返す.

Footnotes

  1. “Thus far, we have presented only examples of functions defined with a single method, applicable to all types of arguments. However, the signatures of method definitions can be annotated to indicate the types of arguments in addition to their number, and more than a single method definition may be provided.” Docs.↩︎

  2. “The choice of which method to execute when a function is applied is called dispatch.” Docs.↩︎

  3. “Multiple dispatch is particularly useful for mathematical code, where it makes little sense to artificially deem the operations to”belong” to one argument more than any of the others: does the addition operation in x + y belong to x any more than it does to y?” Docs.↩︎