fun 함수 이름([변수 이름: 자료형, 변수 이름: 자료형..] ): [반환값의 자료형] {
표현식...
[return 반환값]
}
// 일반적인 함수의 모습
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) 함수는 특정 블록 내에서만 생명주기를 갖고 있기 때문에 블록을 벗어나면 해당 함수는 존재할 수 없게 된다. 이때는 블록 내에서 반드시 먼저 함수 선언을 가지고 있어야만 해당 이름의 함수를 이후에 사용할 수 있다! 추가적으로 함수 뿐만 아니라 함수 내부에서 선언된 변수들도 임시 메모리인 스택에 쌓이고 일정 생명주기를 가지게 된다.
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)
}
max 함수를 호출하면, num1과 num2의 값이 복사되어 매개변수 a, b에 전달된다. 연산이 끝나고 max 함수가 종료되면, 변수 a와 b는 pop 되어서 스택에서 사라진다!
함수가 여러 번 호출되어 더 높은 주소로 진입하면 할수록 그 내용들이 스택에 계속 쌓인다. 그리고 나서 함수가 종료되면 그 내용들이 다시 pop 되어 사라진다!
이것이 바로 함수가 호출되고 종료될 때, 스택 프레임에 일어나는 일들이다! 참고로 힙 메모리는 동적 객체를 할당할 때 사용한다.
하나 이상의 실수를 받아서 모든 실수의 합의 평균을 구하고 그 결과를 출력해보자.
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
}