menu
書いてる野郎
orebike@gmail.com
関数リテラルというか、無名関数を作るということ。
見た目が記号ランランで非常に読みにくいが・・・イコールを挟んで左が入れるための変数宣言で、右が関数本体となる。
val myadd:(Int, Int) => Int = (a:Int, b:Int) => { a + b }:Int
ここが関数を入れる変数宣言。変数名に続き引数の型と戻りの型を型名だで指定している
val myadd:(Int, Int) => Int
ここが関数本体。仮引数に続き処理、最後に戻りの型を指定している。
(a:Int, b:Int) => { a + b }:Int
戻りの型は最後まで読めば Scala では自明になるので書かれることはほぼ無い、かなり高い確率で省略される。
関数の宣言と代入は JavaScript のこのような関係に似ている。
function hoge(a, b){ return a + b; } var hoge = function(a, b){ return a + b };
変数のへの代入であって、宣言ではないので、このようなことができない。
println(myadd(1, 2)) // これはできない val myadd:(Int, Int) => Int = (a:Int, b:Int) => { a + b } println(myadd(1, 2))
def で宣言した関数は引数なしの場合関数名のみで括弧無しで呼び出せるが、 関数リテラルは括弧なしの場合は関数オブジェクトの操作として扱われるので呼び出しには必ず括弧が必要になる。
Scala は関数の記述に関して変形記法がものスゴイたくさんあって、混乱するのでまとめる
関数宣言同様に1ステップの処理ならば中括弧省略が可能になる
var a = () => "hoge"
関数を引数にとる関数のパラメータとしてリテラル表記使う場合。 その関数のシグネチャから引数に取る関数の構造が確定できる部分があるので通常の関数リテラルよりもさらに省略して書くことが可能になる
必要とする関数リテラルの引数が1個の場合その引数指定部分の括弧を省略して書ける
def hoge(f:(Int) => Int):Int = { f(1) } println(hoge(x => x + 1)) // => 2 println(hoge(x => x + 2)) // => 3
必要とする関数リテラルの引数が1個の場合でその関数リテラル中でたった1回しか使われない場合、引数名すら省略して書ける。
この場合アンダースコアが唯一の変数として関数内部で機能する
def hoge(f:(Int) => Int):Int = { f(1) } println(hoge(_ + 1)) // => 2 println(hoge(_ + 2)) // => 3
アンスコを使うことでその周辺が関数であることとなるのだろう。これは若干過激過ぎると思うので
println(hoge({ _ + 1 })) // => 2
このぐらいが優しいと思う
特にこういう用途があるかどうか知らんが JavaScript でやっていたのでできるかなと
(funciton(_hoge){ console.log(_hoge);})("hogehoge");
こういうやつである。
println(((a:Int, b:Int) => { a + b }:Int)(1, 2))
できた!サスガ