読者です 読者をやめる 読者になる 読者になる

opamp_sando's blog

クソザコが割りと適当なことを書くためにある備忘録です。あとたまに普通の日記も書きます

Scalaの関数の引数がよくわからなかった奴 "=>"

Scalaの入門書はひと通り読んだけどよくわからない記述を時々見る。(多分おいらのスペックが低いのだろう)
ということで今日はこんな物をメモっておく。
(間違えてる場合はご指摘してくださると幸いです)

def func(f: => String => Request[AnyContent] => Result) = {...}

これはPlay触ってて見かけた奴。
まあ、Play独特のクラスが入ってきてるのでもっと簡単な感じにすると

def func(f: => String => String) = {....}

と、こんな感じ。

f: => String => String

のように"=>"で始まる奴は名前渡しパラメータというらしい。
空のパラメータ(引数)を省略するために用いられる方法らしく、パラメータに関してだけ存在するということらしい。

なので

def func(f: => String => String => String):String = { ... }

とした場合、パラメータなしでString => String => Stringを返す関数を引数に渡すという感じ。
パラメータは()すら省略できる。
ので、

def func1(f: => String):String = {...}
def func2(f: () => String):String = {...}

func1("hoge")
func2(() => "hoge")

という具合に違いが出てくる。ちなみにfunc1は単純にStringを指定してもいいように見えるが単純にStringを指定するのとは違いがあるらしく、あくまで"関数"を渡している扱いなので評価されるタイミングで違いがでるらしい。

なんか自分で書いてて何いってんだこいつって感じなので実際に動く例を載っけてみる

def hoge(f: => String => String => String):String = {
    f("Hello")("opamp")
}

val func = (greeting:String) => (name:String) => {greeting + " " + name + "!!"}
/*
無駄に括弧をつけてもう少しわかりやすく書くと
val func = (greeting:String) =>{
    (name:String) => {greeting + " " + name + "!!"}
}
という感じ。
戻り値は
(name:String) => {greeting + " " + name + "!!"}
というこれまた関数になっている。(String型を受け取ってString型を返す関数)
*/
println(hoge(func)) // "Hello opamp!!" と表示される

こんな感じ。
またこれで一つの謎が解けた...

ところでこんな書き方もできるらしい

//hogeは同じ
def hoge(f: => String => String => String):String = {
    f("Hello")("opamp")
}

println(hoge {greeting => name => s"$greeting $name!!"})

動作は同じ。 あとこんな書き方も...

def hoge(name:String,greeting:String)(f: => String => String => String):String = {
    f(greeting)(name)
}
println(hoge("opamp","Good luck"){g => n => s"$g $n!!"}

と言うかこれが理解できなくてずーっと迷ってたけどPlayのDocument見に行って理解できた。
呼び出しの部分だけ見るとhogeがいったい何なのかまるでわからない。
どうやら単純にカリー化された関数だったっぽい。

今後もなんかわかんない記述があって理解できたりしたらメモります。

Firefox ブラウザ無料ダウンロード