728x90

closure: 포섭


고차함수 : 함수를 인자로 받거나 함수를 반환하는 함수

클로저 : 고차함수가 반환하는 함수

익명함수 : 이름 없이 임시로 쓰는 함수

람다함수(람다식) : 익명함수의 또다른 이름


함수형 프로그래밍과 더불어 자주 언급되는게 클로져이다.

함수형 프로그래밍에 대해선 설명하지 않겠다.

우리가 중요하게 궁금한건 클로져, 그리고 익명함수이다.


뭐든지 특정 개념에 대해 알려면 그 단어가 가진 뜻을 알아야된다.

우리입장에선 외국인이니까 영어다. 그러니까 뭔가 있어보인다.

그런데 한국말로 바꾸면 클로져는 포섭이라는 뜻이다.

즉, 여기서는 포섭을 써야되. 이런식으로 말하는 꼴이라는 것.


누군가 면접에서 클로져가 뭐냐? 클로져에 대해서 설명해 달라고한적 있다.

거기에 대한 정석적인 대답은 아래와 같다.


선언할 당시의 환경을 기억했다가 나중에 호출될시 원래의 환경에 따라 호출되는 함수


뭔가... 되게 쌩뚱맞는 설명인것 같은 느낌이든다.

하지만 필자는 이를 아주아주 쉽게 설명한다.


함수를 만드는 함수 => 고차함수(고계함수: High-Order Function)

이렇게 함수를 만드는 함수를 고차함수라고 부른다.

그런데 이를 클로저라 불러도 무리는 없다. 엄밀히 말하면 클로저 = 고차함수는 아니다.

예시를 보도록하자.


package main

import "fmt"

func main() {
add5 := outer(5)
fmt.Println(add5(3))
}

func outer(a int) func(int) int{
return func(b int) int {
return a+b
}
}

C, C++, Java를 하다보면 오마이갓...

뭔 회괴망측한 코드가 있다.

당연한 이야기지만 출력결과는 8이 나온다.


함수가 함수를 반환한다고?? 그렇다.

함수가 반환하는 것은 우리가 흔히 아는 "값"이 아니라 "함수다".

아니 더 정확히 말하면 함수가 값이다.


이 때 outer는 우리가 함수를 반환하는 함수이니 고차함수라고 한다.

그리고 이 outer는 클로저를 반환했다 라고 말한다.


outer는 함수를 만드는 함수이며 안의 함수는 그 반환값이 되는 함수이다.

분명 a는 함수 내부에 선언된 값이 아니지만.

외부 함수인 outer함수의 a값을 포섭(closure)해서 자체로 함수로 반환된다.

따라서 이는 클로저라고 부른다.

그리고 클로저를 만들때 대부분의 경우 익명함수(람다함수)를 사용한다.


myFunc := func() string{
return "hello"
}
fmt.Println(myFunc())

익명함수는 이름없는 함수를 의미한다.

다만 자바스크립트 수준의 유연성은 발휘할 수 없지만 그래도 큰 유연성을 발휘하게된다.

익명함수는 람다함수라고도 부른다. 둘이 다라다고 하는 사람들도 존재하긴 하는데...

둘을 굳이 다르게 정의해야하는게 의미있나 싶다. 


그렇다고 모든 클로저는 익명함수인것은 아니다.


myFunc := func() string{
return "hello"
}

yourFunc := func() func() string{
return myFunc
}
fmt.Println(myFunc())
fmt.Println(yourFunc()())

위와 같은 상황에서 yourFunc는 고차함수이며 내부에 클로저를 반환하지만

이 클로저가 익명함수인 것은 아니다. 즉 반드시 람다식을 쓸 필요는 없다.

당연하지만 둘의 결과는 hello로 동일하다.

+ Recent posts