anonymous는 an(without; 없다)+onym(name; 이름)이 합쳐진 글자다.
즉, '이름이 없는(익명의)' 의 뜻이다.
함수에 이름이 없는 이유는 뭘까?
별로 중요하지 않기 때문?
아니다.
중요하고 쓰임새도 많다.
Anonymous Function(익명함수)
익명함수는 말그대로 함수 이름 없이 다른 함수의 전달자 역할을 한다.
'쌩초보 기초 12'에서 익명함수를 람다(lambda)라고 했었다.
코틀린의 표준 라이브러리(내장 함수 모음) 중 count()함수를 사용하여 테스트 해보자.
이 count함수는 문자열에서 호출하면 문자의 개수를 반환해 준다.
4번 라인은 문자열을 변수에 넣고 5번 라인에서 그 변수를 출력하는 코드이다.
7번 라인은 문자열의 개수를 변수에 넣고 8번 라인에서 그 변수를 출력하는 코드이다.
10번 라인은 문자열의 개수를 구하되 count함수의 인자(argument)로 n과 같은 letter를 전달하여 n의 개수를 변수에 넣는다. 본래는 인자를 괄호 안에 넣지만 람다 표현(->)을 사용할 때는 괄호 바깥에 적는다.
11번 라인에서 그 변수를 출력하는 코드이다.
다른 예를 하나 더 보자.
println() 함수도 내장되어 있는 함수이므로 아래와 같은 코드를 만들 수 있다.
println 함수의 괄호( ) 안에 익명함수를 넣을 수도 있다.
4번 라인에서 변수를 만들고 5번 라인에서는 문자열을 만든다.
그리고 다시 ( )괄호를 붙이는 것은 익명함수도 함수이기 때문이다.
println 함수에 익명함수로 호출되었다.
7번 라인처럼 익명함수를 한 줄로 표현할 때는 타입의 값을 분리하기 위해 세미콜론( ; )을 사용한다.
함수 Type(타입)
익명함수가 가지는 타입을 함수타입이라고 한다.
함수타입을 가진 변수 anonymousFunction을 만들어 본다.
위에서 함수타입은 ( ) -> String
이것의 뜻은 다음과 같다.
'인자 없이(빈괄호) String을 반환하는 어떤 함수도 anonymousFunction 변수에 저장될 수 있다'
익명함수는 자동으로 마지막 코드의 결과를 반환하므로 return 키워드가 필요없으며 사용을 금지한다.
함수 인자(argument)
익명함수는 어떤 타입의 인자도 받을 수 있다.
매개변수의 타입은 함수 타입 정의에 지정하고, 매개변수 이름은 함수 내부에 적는다.
익명함수는 코틀린 표준 라이브러리에 있는 대부분의 함수를 구현하는데 사용할 수 있으므로 익숙해지면 유용하다.
위 코드처럼 인자를 한 개만 받을 때는 간편하게 it 키워드를 사용할 수 있다.
name -> 를 지우고 아래와 같이 표현하면 된다.
it키워드의 단점은 매개변수가 무엇인지 잘 알수 없다는 것이다.
되도록이면 매개변수 이름을 적어서 표현하는 것이 좋을 듯하다.
위 코드 중에서 count() { letter -> letter =='n'} 부분을 it키워드를 사용하면 아래와 같다.
it 키워드는 두 개 이상의 매개변수가 있을 때는 사용할 수 없다.
여러 개의 매개변수 사용하려면 콤마( , )로 연결하기만 하면 된다.
또한 일반 함수와 변수의 타입추론 기능도 똑같이 적용된다.
그러므로 인자가 없는 익명함수의 경우 아래 파란색 부분을 생략할 수 있다.
매개변수가 있는 경우에는 생략하고 대신 함수 정의에 매개변수의 타입을 지정해 준다.
매개변수가 여러 개일 때는 마찬가지로 쉼표( , )를 사용해서 나열하면 된다.
함수를 인자로 받는 함수의 정의
함수의 매개변수는 어떤 타입의 인자도 받을 수 있다.
함수도 인자로 받을 수 있다.
runTest 함수가 매개변수로 playerName(플레이어 이름)과 anonymousFuntion 함수를 가진다.
anonymousFuntion 함수는 String, Int 타입을 받아서 Unit타입으로 반환한다.
runTest함수는 lotteryNum변수에 1~5까지 숫자에서 무작위 수를 list로 만들어(shuffled()) 마지막 수를 반환(last())한다.
println함수에서 anonymousFunction함수로 playerName과 lotteryNum를 인자로 전달하여 호출한다.
메인 함수에서는 runTest 함수로 인자를 전달하여 받은 결과를 출력한다.
그런데 위 코드는 뭔가 복잡하고 중복되는 과정을 거치는 느낌이다.
간단하게 수정할 방법을 생각해보자.
runTest 함수가 playerName과 anonymousFunction함수가 매개변수이므로
출력해야 하는 문자열 Wraven은 runText함수의 괄호 안에 넣고 anonymousFunction함수는 앞에서 count() { 람다 } 형태로 했던것 처럼 만들면 아래와 같다.
inline 함수
람다는 유용한 반면 메모리에 부담을 줄 수 있다.
람다를 정의하면 객체를 만들어서 람다를 사용하는 모든 변수를 메모리에 할당한다.
코틀린에서는 메모리 부담을 줄이기 위해 inline(인라인) 키워드를 만들었다.
inline 함수는 모든 내용을 함수가 호출되는 곳에 복사해서 수행하므로 메모리 할당의 부담을 덜어준다.
inline 함수를 만들려면 fun 앞에 붙이면 된다.
참고로 inline 사용이 안되는 경우가 있는데 람다를 인자로 받는 recursive function(재귀함수) 등에서 그렇다.
재귀함수에 대해서는 다음 기회에...
지금까지 람다(익명함수)를 사용해서 다른 함수의 인자로 전달하는 방법을 알아보았다.
다음 글에서는 인자로 전달하는 또 다른 방법인 함수 참조(function reference)를 알아본다.
Wraven...
'프로그래밍 언어 > 코틀린_Kotlin_더파기' 카테고리의 다른 글
Kotlin더파기_06_Null & Exception_널과 예외 (0) | 2020.04.12 |
---|---|
Kotlin더파기_05_Function Reference_함수참조 (0) | 2020.04.12 |
Kotlin더파기_03_Function_함수 (0) | 2020.04.05 |
Kotlin더파기_02_Control Flow 흐름제어 (0) | 2020.04.04 |
IntelliJ인텔리제이 & JDK 설치하기 (0) | 2020.04.03 |