kotlin 技術メモ

kotlin基本構文-関数,引数のデフォルト値,引数の名前付き呼び出し,可変長引数,複数の戻り値,高階関数,ラムダ式

投稿日:

参考にした入門書の内容が薄すぎてトレースする意味がなくなってきた。
いきなり中級書で良かった気がする。

関数

kotlinにおける関数の定義方法。
これもDelphiっぽいけどDelphiの特殊な部分を普通に寄せた感じ。
今思えばDelphiの"関数内の最終評価値が関数の戻り値になる"動きはRubyに通じてるような。
関数の呼び出しに使ったスタックをどう解釈するかの違いだから似たパターンになるんだろう。

関数の定義において、引数の型を省略することはできない。
以下はN.G.

戻り値が無い関数を定義する際は、戻り値の型をUnit型にする。
なお、関数の戻り値のUnit型のみ省略可能。

よくある省略形として、関数本体が1行しかない場合はブラケットを省略できるけど、
kotlinも省略できる。ただし書き方が少し違う。
コンパイラがワンライナーの型を推測できる場合は、関数の戻り値の型自体を省略できる。

引数のデフォルト値

よくある引数のデフォルト値定義。普通。

デフォルト値ありの引数と無しの引数を混在させることもできる。
必須引数は引数リストの先頭に、省略可能引数は引数リストの後方に置くこと。

引数のデフォルト値にはリテラルだけでなく関数の戻り値を指定することができる。
これは新感覚。

引数の名前付き呼び出し

関数の呼び出し時に引数の名前を指定することができる。
ほんと、どっかで見た最近の言語のつまみ食い。
引数の順序に縛られない、引数の順序によらずどの引数も省略できる。

kotlinはJavaのコードを呼び出せる(はず)だけれども、
Javaのバイトコードは引数の名前を保持していないため、
Javaのメソッドを名前付き引数を使って呼び出すことはできない。

可変長引数

だいたいどの言語にもある可変長引数。
使ったこと無いけど。
他の変数と混在させる場合は、可変長引数を末尾に配置すること。
可変長引数を前に持ってくる場合、呼び出し時にどこまでが可変長引数かわからなくなるので、
可変長引数の後の引数を名前付きで渡す必要がある。(そこまでして順番に拘る必要はないと...)

可変長引数として配列を渡すことができる。
その際、配列の先頭にスプレット演算子(*)を置く。
ポインタ、参照とは関係なく、
単に配列を可変長引数に展開することから"spread"という名前になっている。

スプレッド演算子を使うと、リテラルと配列から1つの可変長引数を作れる。
こんなことしないと思うんだけど。

複数の戻り値

これは鮮やか。関数が複数の戻り値を返せる。
鮮やかだけども型として常用してはいけない様子。関数の戻り値を受け取る時ぐらいで留めるべき。
以下は、可変長引数で渡した値の算術平均を返す関数。

Pairをそれぞれの変数にバラすのは以下の通り。

高階関数

関数の参照を渡すには以下のようにする。
Int型の引数を出力する関数printを、配列のforEachに渡している。
配列のforEachの繰り返しの度にprint関数が評価される。
その際、引数itemとして配列の各要素が渡される。

もちろん、関数をラムダ式に置き換えることができる。
ブラケットで囲まれた部分がラムダ式。
arrow(->)の左辺がラムダ式のパラメタ、右辺が関数の本体。

ラムダ式のパラメタの型はコンパイラの型推論で自動的にわかるのなら省略できる。

ラムダ式を与える引数リストにおいて、ラムダ式が最後である場合、
引数リストからラムダ式を除いて以下のようにかける。

さらに、ラムダ式を与える引数リストにおいて、引数がラムダ式しかない場合、
引数リストの空プラケットさえ省略できる。

そして、ラムダ式に与える引数が一つしかない場合、暗黙の引数itを宣言無しで使える。

ラムダ式と匿名関数

あまりラムダ式と匿名関数の違いについて考えたことがなかったのだけども、
ラムダ式の代わりに匿名関数を渡すことができる。同じ意味になる。
ラムダ式は匿名関数の糖衣構文(Syntax sugar)である。
つまり冗長な匿名関数を簡易な書き方で書き直したのがラムダ式である。
下記の通り、匿名関数は冗長。

ラムダ式内でのreturn

Rubyで一つの話題になるラムダ式内でのreturnについて。
kotolinにおいてラムダ式内でreturnすると、該当のラムダ式ではなく直上の関数を抜ける意味になる。
下記はラムダ式を中断するだけでなくary.forEachを包含する関数も中断する。
従って、末尾のprintln("OK")は処理されず、OKは出力されない。

ラムダ式のみを中断するにはラベル構文を使用する。
下記のようにloopラベルを書いておくと、ラムダが中断したとき中断の連鎖はloopラベルで終了する。
これは自棄っぱちな感じがするな。Rubyと同等で良いんじゃなかろうか。

高階関数サンプル

高階関数のサンプル。ある時間がかかる処理を関数として実装し、
高階関数にその関数を渡す。
高階関数側では、その関数の実行前後の時間を計測し経過時間を出力する。

ローカル関数

関数内で関数を定義することでスコープを限定できる。
内側の関数からは外側の関数のスコープにある変数を参照できる。

-kotlin, 技術メモ
-

Copyright© ikuty.com , 2018 AllRights Reserved Powered by AFFINGER4.