====== 標準関数・スコープ関数 ======
===== apply =====
レシーバーに対して一連の関数を呼びだすことでレシーバーに対する設定ができる。
// 定義
public inline fun T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
// サンプル
val file= File("text.txt").apply {
setReadable(true)
setWritable(true)
setExecutable(true)
}
===== let =====
渡されたラムダにitで参照できるようにする。
// 定義
public inline fun T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
// サンプル
val value = listOf(1,2,3).shuffled().first().let { it*it }
println(value)
// null合体演算子との組み合わせ
^ 関数 ^ 渡し | 関数コール ^ 返し ^
| apply | 何も渡さない | 相対スコープ | レシーバー |
| let | レシーバーをラムダに渡す | ー | ラムダの最後の行 |
| run | | 相対スコープ | ラムダの最後の行 |
| | | | |
===== run =====
applyと同じく関数は相対スコープで呼び出されるが、何も返さない。
runを使った呼び出しの連鎖のほうがネストしているよりわかりやすい。
fun nameIsLong(name:String) = name.length > 10
fun playerCreateMessage(nameTooLong:Boolean):String{
return if (nameTooLong){
"too long"
}else{
"welcome!!"
}
}
fun main(){
// runによる関数呼び出しの連鎖
val text = "polarcubis,supreme master5 of nyethack"
.run(::nameIsLong) // >>> true
.run(::playerCreateMessage) // >>> too long
.run(::print)
}
}
>>> too long
===== with =====
引数を第一パラメーターとして受け取る必要がある。
可能ならばrunで置き換える。
===== also =====
let とにているが、letはラムダの結果を返す。
alsoはレシーバーを返す。
===== takeif =====
真だとレシーバーを返す。
偽だとnullを返す
===== takeUnless =====
偽だとレシーバーを返す。
真だとnullを返す。
わかりにくいため使用すべきではない。