Lesson 2: Functions

HanbinΒ·2021λ…„ 8μ›” 4일
0

Teach Android Development

λͺ©λ‘ 보기
2/13
post-thumbnail

πŸ’‘ 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

  • ν•¨μˆ˜λŠ” variables 및 data structures에 μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • λ‹€λ₯Έ higher-order functions에 arguments둜 μ „λ‹¬λ˜κ³  λ°˜ν™˜λ  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 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()λ₯Ό μ‚¬μš©ν•΄μ„œ Sequencesλ₯Ό list둜 되돌릴 수 μžˆμŠ΅λ‹ˆλ‹€.

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]

0개의 λŒ“κΈ€