Lesson 2: Functions


💡 Teach Android Development


Googleが提供するトレーニング資料を整理するための記事です.
Android Development Resources for Educators

(Almost) Everything has a value


(Almost) Everything is an expression


kotlinでは、ほとんどのコンテンツが式であり、値があります.
val temperature = 20
val isHot = if (temperature > 40) true else false
println(isHot) // false

Expression values

Kotlin.Unitは、この値であってもよい.
val isUnit = println("This is an expression")
isUnit // This is an expression
println(isUnit) // Kotlin.Unit
注意:Kotlin.UnitJavaでの役割はvoidと同じです.
Javaではvoidは戻り値がないことを示すが、Kotlin.Unitはパラメータとしても使用できる.

Functions in Kotlin

  • 特定の動作を実行するコードブロック.
  • 大きなプログラムを小さなモジュールに分割
  • funキーワード宣言
  • パラメータとして指定値またはデフォルト値を使用できます
  • Parts of a function


    「Hello World」の簡単な例を印刷します.
    fun printHello() {
        println("Hello World")
    }
    printHello()

    Unit returning functions


    関数が値を返さない場合、retrun typeはUnitであり、受け入れられる.
    fun printHello(name: String?): Unit {
        println("Hi there!")
    }

    Function arguments


    Default parameters


    パラメータのデフォルト値を設定できます.
    fun drive(speed: String = "fast") {
       println("driving $speed")
    }
    
    drive() ⇒ driving fast
    drive("slow") ⇒ driving slow
    drive(speed = "turtle-like") ⇒ driving turtle-like

    Required parameters


    パラメータにデフォルト値がない場合は、強制的に実行します.
    fun tempToday(day: String, temp: Int) {
        println("Today is $day and it's $temp degrees.")
    }
    tempToday("monday", 35)

    Default versus required parameters


    デフォルトパラメータと必須パラメータを混在させることができます.
    fun reformat(str: String,
    	     divideByCamelHumps: Boolean,
                 wordSeparator: Char,
                 normalizeCase: Boolean = true){ }
    
    reformat("Today is a day like no other day", false, '_')

    Named arguments


    必須変数に指定した変数を使用して、可読性を向上させます.
    Keyword arguments(str)をPositional arguments(divideByCamelHumps)の後に置くのは良いスタイルです.
    reformat(str, divideByCamelHumps = false, wordSeparator = '_')

    Single-expression functions


    より簡潔で読みやすい.
    fun double(x: Int): Int {
        x * 2
    }
    
    fun double(x: Int):Int = x * 2
    

    Lambdas and higher-order functions


    Kotlin functions are first-class

  • 関数はvariablesおよびdata structuresに保存できます.
  • は、他のhigher-order functionsに転送および戻ることができる.
  • arguments新しい組み込み関数を作成できます
  • Lambda functions


    匿名関数の式を作成します.
    var dirtLevel = 20
    val waterFilter = {level: Int -> level / 2}
    println(waterFilter(dirtLevel)) // 10
  • level:Int:パラメータとタイプ
  • ->: Function arrow
  • level/2:実行するコード
  • Syntax for function types


    function type構文とramda構文は相互に関連している.
    val waterFilter: (Int) -> Int = {level -> level / 2}
  • waterfilter:変数名
  • (Int)->Int:function type構文
  • {level->level/2}:ランダ構文
  • Higher-order functions


    パラメータまたは戻り関数として関数を使用します.
    fun encodeMsg(msg: String, encode: (String) -> String): String {
        return encode(msg)
    }
    2番目のhigher-order functionsに渡される関数を呼び出し、1番目のargumentを渡します.
    上記の関数を呼び出すには、argumentとを転送する必要があります.
    val enc1: (String) -> String = { input -> input.toUpperCase() }
    println(encodeMsg("abc", enc1))
    この方法は実施と使用を別々にする.

    Passing a function reference

    String演算子を使用して、指定された関数を他の関数::に転送します.
    fun enc2(input:String): String = input.reversed()
    encodeMessage("abc", ::enc2) // 지정된 함수를 전달하며, 람다 방식이 아닙니다.
    argumentで宣言される方法は、argument演算子で指定された関数と同じでなければなりません.

    Last parameter call syntax


    関数を使用するすべてのパラメータは、最後のパラメータであることが望ましい.
    encodeMessage("acronym", { input -> input.toUpperCase() })
    カッコで囲まずにパラメータを渡すことができます.
    encodeMsg("acronym") { input -> input.toUpperCase() }

    Using higher-order functions


    kotlinの多くの組み込み関数は、最後のパラメータを使用して構文定義を呼び出します.
    inline fun repeat(times: Int, action: (Int) -> Unit)
    
    repeat(3) {
        println("Hello")
    }

    List filters

    ::のリストには、特定の条件を満たす項目が含まれています.

    Iterating through lists

    listパラメータが1つしかない場合は、宣言およびfunction literalを省略できます.パラメータは->として表され、暗黙的に宣言されます.
    val ints = listOf(1, 2, 3)
    ints.filter { it > 0 }
    フィルタ繰返しit,collectionは繰返し期間itの値である.
    以下に示すことができます.
    ints.filter { n: Int -> n > 0 }
    
    ints.filter { n -> n > 0 }

    List filters


    フィルタを繰り返すと、カッコelementの条件が実行され、条件が{}の場合、アイテムが含まれます.
    val books = listOf("nature", "biology", "birds")
    println(books.filter { it[0] == 'b' }) // [biology, birds]

    Eager and lazy filters

    trueの式の評価
  • Eager:結果が使用されているかどうかにかかわらず、
  • が励起されます.
  • Lazy:実行時にのみ発生
  • listLazy評価は完全な結果を必要としないか、またはlistが大きく、複数のコピーのメモリ浪費を回避します.

    Eager filters


    デフォルトでは、フィルタはEagerです.フィルタを使用するたびに、新しいlistが作成されます.
    val instruments = listOf("viola", "cello", "violin")
    val eager = instruments.filter { it [0] == 'v' }
    println("eager: " + eager) // eager: [viola, violin]

    Lazy filters

    listはLazy評価を用いたSequencesである.フィルターと一緒にLazyが使えます
    val instruments = listOf("viola", "cello", "violin")
    val filtered = instruments.asSequence().filter { it[0] == 'v'}
    println("filtered: " + filtered) // filtered: kotlin.sequences.FilteringSequence@386cc1c4

    Sequences -> lists

    data structuresを使用して、toList()Sequencesに復元できます.
    val filtered = instruments.asSequence().filter { it[0] == 'v'}
    val newList = filtered.toList()
    println("new list: " + newList) // new list: [viola, violin]
    注意:フィルタを連続的に使用する場合、Eagerモードでは、各フィルタは新しいlistを作成し、条件を満たす新しいlistを返します.これに対してLazyはすべての条件を処理してlistを返す.

    Other list transformations

  • listは、すべての項目を同じ変換を行い、map()を返します.
  • val numbers = setOf(1, 2, 3)
    println(numbers.map { it * 3 }) // [3, 6, 9]
  • listすべてのネストflatten()collectionsを1つのelements|に戻します.
  • val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5), setOf(1, 2))
    println(numberSets.flatten()) // [1, 2, 3, 4, 5, 1, 2]