[Kotlin] 3-1. 함수 선언 및 호출

leeeha·2022년 6월 20일
0

코틀린

목록 보기
8/28
post-thumbnail

출처: https://www.boostcourse.org/mo132/lecture/59973

함수

fun 함수 이름([변수 이름: 자료형, 변수 이름: 자료형..]  ): [반환값의 자료형] { 
    표현식...
    [return 반환값] 
}

sum 함수

// 일반적인 함수의 모습 
fun sum(a: Int, b: Int): Int {
    return a + b
}

// 간략화 된 함수 
fun sum(a: Int, b: Int): Int = a + b

// 리턴 타입 생략 
fun sum(a: Int, b: Int) = a + b

리턴 값이 없을 때는? Unit으로 자료형을 지정하거나 생략한다.

사용자 정의 함수는 main 함수의 위치와 상관 없이 사용될 수 있다.

package chap03.section1

fun sum(a: Int, b: Int): Int { // main 함수 이전 
    return a + b
}

fun main() {
    val result1 = sum(1, 2)
    println(result1)
}
package chap03.section1

fun main() {
    val result1 = sum(1, 2)
    println(result1)
}

fun sum(a: Int, b: Int): Int { // main 함수 이후 
    return a + b
}
package chap03.section1

fun main() {
    fun sum(a: Int, b: Int): Int { // main 함수 안 
        return a + b
    }
    
    val result1 = sum(1, 2)
    println(result1)
}

하지만 다음과 같은 경우는 불가능하다.

package chap03.section1

fun main() {
    val result1 = sum(1, 2) // sum 함수 인식 불가! 
    println(result1) 
    
    fun sum(a: Int, b: Int): Int { 
        return a + b
    } // main 함수 내의 '지역 함수' 
}

위처럼 특정 함수 내에 포함된 지역 함수가 아니라, 클래스나 함수 가장 바깥에 정의된 함수최상위 (top-level) 함수라고 부른다.

📌 부연 설명
코틀린은 따로 클래스를 만들지 않아도 함수를 생성할 수 있다. main()처럼 클래스 멤버가 아닌 파일에서 직접 작성되는 함수는 최상위(top-level) 함수라고 불리며, 이런 함수는 메모리에 고정적으로 존재하기 때문에 어느 위치에서든지 함수를 호출할 수 있다.
반면에 지역(local) 함수는 특정 블록 내에서만 생명주기를 갖고 있기 때문에 블록을 벗어나면 해당 함수는 존재할 수 없게 된다. 이때는 블록 내에서 반드시 먼저 함수 선언을 가지고 있어야만 해당 이름의 함수를 이후에 사용할 수 있다! 추가적으로 함수 뿐만 아니라 함수 내부에서 선언된 변수들도 임시 메모리인 스택에 쌓이고 일정 생명주기를 가지게 된다.

max 함수

package chap03.section1

fun sum(a: Int, b: Int): Int { // 여기서 a와 b는 parameter(매개변수)
    return a + b
}

// 전달 받은 인자와 매개변수는 서로 다른 변수다! 매개변수에 값이 복사되는 것!
fun max(a: Int, b: Int): Int {
    return if(a > b) a else b
}

fun main() {
    val result1 = sum(2, 3) // 여기서 a와 b는 argument(인자)
    println(result1)

    val a = 3
    val b = 5
    val result2 = max(a, b)
    println(result2)
}

리턴 값이 없는 경우

fun outFunc(name: String): Unit {
    println("name: $name")
    //return Unit // 사실은 이게 생략된 것! 
}

fun main() {
    outFunc("Hello") 
}

리턴 타입 생략

package chap03.section1

fun sum(a: Int, b: Int) = a + b

fun max(a: Int, b: Int) = if(a > b) a else b

fun outFunc(name: String) = println("name: $name")

fun main() {
    val result1 = sum(2, 3)
    println(result1)

    val a = 3
    val b = 5
    val result2 = max(a, b)
    println(result2)

    outFunc("Hello")
}

매개변수에 디폴트 값 지정하기

package chap03.section1

fun sum(a: Int = 2, b: Int = 5) = a + b

fun main() {
    val result1 = sum(2, 3)
    val result2 = sum(2)     // b는 디폴트 값으로
    val result3 = sum(b = 4) // a는 디폴트 값으로 (매개변수의 이름과 함께 인자를 전달하는 경우) 
    println(result1)
    println(result2)
    println(result3)
}

가변 인자 (variable arguments)

함수와 스택 프레임 이해하기

max 함수를 호출하면, num1과 num2의 값이 복사되어 매개변수 a, b에 전달된다. 연산이 끝나고 max 함수가 종료되면, 변수 a와 b는 pop 되어서 스택에서 사라진다!

함수가 여러 번 호출되어 더 높은 주소로 진입하면 할수록 그 내용들이 스택에 계속 쌓인다. 그리고 나서 함수가 종료되면 그 내용들이 다시 pop 되어 사라진다!

이것이 바로 함수가 호출되고 종료될 때, 스택 프레임에 일어나는 일들이다! 참고로 힙 메모리는 동적 객체를 할당할 때 사용한다.

함수 구현 예제

하나 이상의 실수를 받아서 모든 실수의 합의 평균을 구하고 그 결과를 출력해보자.

  • 초기값을 위한 인자는 Float형
  • 초기값에 아무런 인자를 입력하지 않으면 0을 기본으로 사용
  • 두번째부터 받아들일 인자는 가변형 인자로 모두 실수형 Float
  • 반환값은 모든 인자의 평균값으로 마찬가지로 실수형 Double
package chap02.section4

fun avgFunc(initial: Float = 0f, vararg numbers: Float): Double {
    var sum = 0f
    for(num in numbers){
        sum += num
    }
    println("sum: $sum, numbers.size: ${numbers.size}")

    val avg = if(initial != 0f){
        (initial + sum) / (numbers.size + 1)
    }else{
        sum / numbers.size
    }

    return avg.toDouble()
}

fun main() {
    val a = avgFunc() // 0을 0으로 나누게 됨. 
    println("avg: $a") // NaN 
    
    val b = avgFunc(initial = 5f) // initial 그대로 출력 
    println("avg: $b") // 5.0 
    
    val c = avgFunc(5f, 100f, 90f, 80f) // 모든 인자들의 평균 
    println("avg: $c") // 68.75 
}
profile
꾸준히!

0개의 댓글