Lesson 2: Functions

8088 단어 androidkotlinandroid

💡 Teach Android Development

구글에서 제공하는 교육자료를 정리하기 위한 포스트입니다.

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

note: Kotlin.Unit은 자바에서 void와 같은 역할을 합니다.
자바에서 void는 리턴값이 없음을 나타내지만 Kotlin.Unit은 인자로도 사용할 수 있습니다.

Functions in Kotlin

  • 특정 작업을 수행하는 코드 블록입니다.
  • 큰 프로그램을 작은 module로 나눕니다.
  • fun 키워드를 사용하여 선언합니다.
  • 지정된 값이나 기본값을 인자로 받을 수 있습니다.

Parts of a function

"Hello World" 를 출력하는 간단한 예제입니다.

fun printHello() {
    println("Hello World")
}
printHello()

Unit returning functions

함수의 return값이 없을 경우 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

가독성을 높이기 위해 필수 변수에 대해 지정된 변수를 사용합니다.
Positional arguments(str) 뒤에 Keyword 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

  • 함수는 variablesdata structures에 저장할 수 있습니다.
  • 다른 higher-order functionsarguments로 전달되고 반환될 수 있습니다.
  • higher-order functions을 사용하여 새로운 내장 함수를 생성할 수 있습니다.

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

funtion type의 구문과 람다 구문은 서로 연관되어 있습니다.

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)
}

두번째 argument로 전달된 함수를 호출하고 첫번째 argument를 전달합니다.

위의 함수를 호출하려면 String과 함수를 전달 해야합니다.

val enc1: (String) -> String = { input -> input.toUpperCase() }
println(encodeMsg("abc", enc1))

이러한 방식을 사용하면 구현과 사용법이 분리됩니다.

Passing a function reference

:: 연산자를 사용하면 지정된 함수를 다른 함수에 대한 argument로 전달합니다.

fun enc2(input:String): String = input.reversed()
encodeMessage("abc", ::enc2) // 지정된 함수를 전달하며, 람다 방식이 아닙니다.

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

list의 목록 중 특정 조건에 만족하는 항목을 가져옵니다.

Iterating through lists

function literal에 매개변수가 하나만 있는 경우 해당 선언과 ->를 생략할 수 있습니다. 매개변수는 it이라 표현하며 암시적으로 선언됩니다.

val ints = listOf(1, 2, 3)
ints.filter { it > 0 }

필터는 collection을 반복하며 it은 반복하는 동안 element의 값입니다.

아래와 같이 표현할 수 있습니다.

ints.filter { n: Int -> n > 0 }

ints.filter { n -> n > 0 }

List filters

중괄호{} 안의 조건은 필터가 반복될 때 수행되며, 조건이 true일 경우 항목을 포함 시킵니다.

val books = listOf("nature", "biology", "birds")
println(books.filter { it[0] == 'b' }) // [biology, birds]

Eager and lazy filters

list의 표현식 평가

  • Eager: 결과가 사용되었는지 관계없이 발생
  • Lazy: runtime 시 필요한 경우에만 발생

list Lazy 평가의 경우 전체 결과가 필요하지 않거나 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

Sequences는 Lazy 평가를 사용하는 data structures이다. 필터와 함께 사용해서 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

toList()를 사용해서 Sequenceslist로 되돌릴 수 있습니다.

val filtered = instruments.asSequence().filter { it[0] == 'v'}
val newList = filtered.toList()
println("new list: " + newList) // new list: [viola, violin]

note: 필터가 연속적으로 사용되면 Eager 방식의 경우 각각의 필터에서 새로운 list를 생성하고 조건에 일치하는 새 list return 합니다. 반면에 Lazy 방식의 경우 모든 조건을 처리한 뒤 list를 return 합니다.

Other list transformations

  • map()은 모든 항목에 대해 동일한 transform을 진행하고 list를 return 합니다.
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 }) // [3, 6, 9]
  • flatten()은 중첩된 collections에 대한 모든 elements를 하나의 list로 return 합니다.
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5), setOf(1, 2))
println(numberSets.flatten()) // [1, 2, 3, 4, 5, 1, 2]

좋은 웹페이지 즐겨찾기