다트의 함수
다트는 완전한 객체 지향 언어이다. 따라서 다트에서는 모든 것이 객체이기 때문에 함수도 객체이다. 자바스크립트는 잘 모르지만 자바스크립트도 함수가 객체라고 한다. 자바스크립트의 자리를 노리던 다트의 야심을 엿볼 수 있는 부분이다.
함수가 객체이기 때문에 갖는 특징이 있다. 먼저 변수가 함수를 참조할 수 있다. 그리고 함수의 인자로 함수를 전달할 수도 있다. 이런 내용은 특별히 새로운 내용은 아니다.
어쩌면 조금 새로울 수 있는 내용도 있다. 바로 '선택 매개변수(optional parameter)'이다. 선택 매개변수는 또 두 가지로 나뉜다. 하나는 '이름 있는 선택 매개변수(named optional parameter)'이고 다른 하나는 '위치적 선택 매개변수(positional optional parameter)'이다.
하지만 이 개념이 다트에서 처음 도입된 것은 아니다. 예를 들면 코틀린에서도 같은 기능을 제공한다.
그리고 익명 함수(anonymous function)를 지원한다. 익명 함수가 등장했으니 친구인 람다식(lambda expression)도 지원한다.
다트 함수의 특징을 요약하면 크게 다음과 같다.
1) 변수가 함수 참조 가능
2) 다른 함수의 인자로 함수 전달 가능
3) 이름 있는 선택 매개변수
4) 위치적 선택 매개변수
5) 익명 함수 및 람다
그러면 함수에 대해서 하나씩 살펴보자.
1. 변수가 함수 참조 가능
아래 코드를 보면 var 타입 name 변수가 문자열을 리턴해주는 getName() 함수를 참조한다. 그러면 name은 문자열을 값으로 가지기 때문에 String 타입이 된다. 흔하게 사용하는 함수 호출의 형태이다.
타입 변수명 = 함수() { }
ex) var name = getName() { }
또 한 가지! add() 함수를 보면 함수 리턴 타입과 매개변수 타입이 지정되어 있다. 하지만 sub() 함수에는 타입이 지정되지 않았다. 이렇게 생략 가능하긴 하지만 가급적 명시하는 것이 좋다.
2. 다른 함수의 인자로 함수 전달 가능
아래 코드를 보면 multi() 함수의 첫 번째 매개변수에 add(a, b)를 두 번째 매개변수에 sub(a, b)를 넘겨주었다. 그러면 multi() 함수의 첫 번째 인자는 add(a, b) 리턴 값인 15가 되고 두 번째 인자는 sub(a, b)의 리턴 값인 5가 된다. 그리고 두 인자를 곱한 값이 multi() 함수의 리턴 값이 된다.
함수A(함수B(), 함수C()) { }
ex) getName(getFirstName(), getLastName()) { }
3. 이름 있는 선택 매개변수
함수 호출 시 매개변수에 인자 값을 넘겨줄 때 매개변수명을 이용하여 인자 값을 넘겨줄 수 있다. 매개변수명으로 인자 값을 넘겨줄 매개변수는 { }로 감싸줘야 한다.
getAddress (String 매개변수명1, {String 매개변수명2, String 매개변수명3 }) { }
ex) getAddress(‘seoul’, {매개변수명2: ‘gangnam’, 매개변수명3: ‘123’}) { }
아래 예제는 기본 형태에서 약간 변형을 주었다. district, zipCode를 선택 매개변수로 지정하였고 zipCode는 초깃값을 가지도록 했다.
그러면 첫 번째 print() 함수처럼 zipCode에 대한 인자 값이 없으면 초깃값을 사용한다.
두 번째 print() 함수처럼 새로운 인자 값을 넘겨주면 그 값으로 할당된다.
마지막 주석 처리된 세 번째 print() 함수처럼 필수 매개변수와 혼용할 때는 기본 매개변수에 대한 인자 값을 누락하면 안 된다.
4. 위치적 선택 매개변수
앞선 이름 있는 선택 매개변수에서 zipCode의 초깃값을 지정한 형태를 살펴봤다. 비슷한 개념이다. 위치적 선택 매개변수는 미리 초깃값을 지정해놓고 함수 호출 시 해당 매개변수에 인자 값을 넘겨주지 않으면 초깃값을 사용하는 것이다.
선언 방법은 선택 매개변수 지정을 { } 대신에 [ ]로 하는 것이 차이점이다.
함수(매개변수, [매개변수 = 초깃값, 매개변수 = 초깃값]) { }
ex) getAddress(city, [district = '강남', zipCode = '111222']) { }
초깃값을 변경하고 싶으면 새로운 인자 값을 넘겨주면 된다. 주의할 점은 이름 있는 선택 매개변수와 마찬가지로 필수 매개변수는 꼭 인자 값을 줘야 하고 매개변수 위치를 꼭 고려해야 한다. 예를 들면 getAddress('서울', '012345')와 같이 호출한다고 해서 zipCode가 변경되는 것이 아니라 district가 변경된다.
5. 익명 함수 및 람다식
다트 공식문서에는 익명 함수를 람다 또는 클로저(closure)라고도 부른다고 설명해놨다. (좀 다른 거 같은데..)
익명 함수의 기본 형태는 다음과 같다.
(매개변수명) { 표현식; };
ex) (a, b) { a + b; };
람다식의 기본 형태는 다음과 같다.
(매개변수명) => 표현식;
ex) (a, b) => a - b;
익명 함수와 람다식의 차이점을 보면 결국 { };를 =>로 변경한 것 밖에 없다. 그래서 친구라고 말했던 것이다. 실제로 어떻게 쓰이는지는 다음 예제를 참고하면 된다.