z

BLOG ARTICLE closure | 1 ARTICLE FOUND

  1. 2010.08.12 Closure

Closure

개발 2010. 8. 12. 09:08


원본 : http://www.martinfowler.com/bliki/Closure.html

다른 번역본 : http://tong.nate.com/sasasasacom/36780536

동적 언어dynamic languages에 대한 관심이 증가하면서, 더 많은 사람들이 Closures 또는 Blocks에 개념 프로그래밍에 관심을 가지기 시작했다. C/C++/JAVA/C#언어 배경을 가진 사람들은 closures를 사용할수 없었고 그 결과 그것이 무엇인 확실하게 알지 못한다. 여기 간단한 설명이 있다. 이 기능을 가진 언어에 꽤나 깊은 지식을 가지고 있는 사람은 이설명에 흥미가 없을수도 있다.

Closures는 오래전부터 주위에 있었다. 나는 이 기능을 Smalltalk에서 사용하였고 Blocks라고 불렀다. Lisp에서는 이 기능을 꽤나 많이 사용했다. 이 기능들은 Ruby  스크립트 언어에도 지원된다. - 그리고 스크립트 언어로 Ruby를 사용하기를 좋아하는 많은 루비스트들의 사용하는 주요한 이유이기도 하다.


본래 closure는 함수 호출에 인수argument를 전달할 수 있는 코드 블록이다. 이것을 간단한 예제로 표현해보겠다.

종업원 객체employee objects 리스트가 있다고 가정하자. IsManager 속성property로 정의된 매니저인 종업원 리스트를 얻고자 한다면 C#을 사용한다면 이와 같이 표현할 것이다.

public static IList Managers(IList emps) { IList result = new ArrayList(); foreach(Employee e in emps) if (e.IsManager) result.Add(e); return result; }

Closures를 사용한 언어, 이 경우에는 Ruby의 예를 들면 다음과 같이 작성할수 있다.


def managers(emps)
  return emps.select {|e| e.isManager}
end
본래 select는 Ruby Collection class에 정의된 메소드이다. 이 메소드는 code block, closure을 인수argument로  가졌다. 
Ruby에서는 curlies사이에 code block을 작성할수 있다(유일한 방법은 아니다). 만일 code block이 어떠한 인수들을 가져야한다면,
vertical bar 사이에 이것들을 정의하면 된다. select 메소드에서는 입력된 array를 돌면서iterate 요소들에 code block을 실행하는 것이다.
그리고 이 block code가 참인 요소들을 모아서 array로 반환하는 것이다.
이제ㄴ 당신이 C Programmer라면 아마도 "나는 function pointer로 이것을 할수 있어" 라고 생각할지도 모른다. 만일 당신이 java 프로그래머라면
"나는 이것을 anonymous inner class로 해결할수 있어" 라고 생각할수도 있고, C# 프로그래머는 delegate를 고려할지도 모른다. 이 mechanism들은
closure와 비슷하다. 그러나 두가지 다른점이 있다.
첫번째는 형식적인 차이formal difference이다. closure는 그것들이 정의된 시점에 변수 가시visible을 참조할수 있다. 
다음 메소드를 고려해보자.
def highPaid(emps) threshold = 150 return emps.select {|e| e.salary > threshold} end
 
select메소드 block안의 코드는 select메소드를 포함하고 있는 상위 메소드에 정의된 지역변수를 참고하고 있다.(threshold) 
실제 closure를 지원하지 않는 언어들에서 closure의 대안으로 사용하는 많은 것들은 이것을 지원하지 않는다.
Closure는 더욱 더 흥미를 끄는 요소를 지원한다. 이 함수를 살펴보자.
 def paidMore(amount) return Proc.new {|e| e.salary > amount} end
이 함수는 closure를 리턴하고 있다. 실제로 인수에 따라 동작하는 closure를 반환한다. 
변수를 넣어서 다음과 같은 기능을 만들수 있다.
highPaid = paidMore(150)

highPaid라는 변수는 salary라는값이 150보다 큰지 검사후 결과를 반환하는 code block을 포함하고 있다.
나는 이와 같이 이 기능을 사용할 것이다.

 john = Employee.new
john.salary = 200
print highPaid.call(john)

highPaid.call(john)이라는 표현은 코드내의 amount 변수가 proc 객체를 생성할때 전달한150보다 큰지 판단하고  이전에 정의했던 e.salary > amount  코드를 호출한다. 비록 150이라는 값이 print 를 호출할때 영역 밖에 위치해 있다하더라도, 바인딩은 여전히 남아있게 된다. 그래서 closure에 대해서 첫번째 중요한 점은 closure가 만들어지는 환경에서 바인딩된 code block이라는 것이다. 이것은 function pointer와 비슷한 기술들과 closure를 구분할수 있는 다른 형식이라는 점이다.(자바의 anonymous inner class는 지역 변수를 접근할수 있다. - 하지만 final 인 경우에만 가능하다)


두번째 차이점은 그다지 정의된 형식defined formal이 없다는 점(편하게 쉽게 사용할수)이다. closure를 지원하는 언어들은 매우 간략한 문법으로 정의할수 있도록 한다. 이것은 그다지 중요한 점이 아닐수도 있겠지만, 나는 이것이 매우 중요하다고 믿는다 - 자연스럽게 이 기능들을 자주 사용할수 있게 해주는 핵심이다. Lisp, Smalltalk, Ruby code를 보라 그러면 closure를 모든곳에서 사용되고 있음을 알수 있을것이다. - 다른 언어에서의 비슷한 구조보다 더 많이 자주 사용된다. 지역변수를 바인드 할수 있는 능력이 있는 점일수도 있겠지만, 나는 큰 이유는 간단 명료하게 사용할수는 문법 때문이라 생각한다.


이 요점의 좋은 경우는 이전 smalltalker들이 자바를 시작할때 어떠했었는가이다. 초반에 나를 포함한 많은 사람들이 anonymous inner class를 smalltalk의 block으로 되었던 많은 부분에 사용하려고 시도했었따. 그러나, 결과적으로 code가 너무 뒤범벅이었고, 추해서 우리는 포기했었다.


Like any term in software there is a lot of blur about the exact definition of closure. Some people say that the term only applies to an actual value that includes bindings from its environment, such as the value returned by highPaid. Others use the term 'closure' to refer to a programming construct that has the ability to bind to its environment. This debate, an example of the TypeInstanceHomonym, is usually carried out with the politeness and lack of pedantry that our profession is known for.

I use closures a lot in Ruby, but I don't tend to create Procs and pass them around. Most of the time my use of closures is based around CollectionClosureMethods similar to the select method I showed earlier. Another common use is the 'execute around method', such as when processing a file.

File.open(filename) {|f| doSomethingWithFile(f)}
여기 open 메소드는 파일을 열고, 제공된 block을 실행하며, 닫는다. transaction(commit 또는 rollback을 기억해야하는)과 같은 곳 또는 
마지막에 어떤것을 기억해서 해야만하는 곳에 편하게 사용할수 있다. 나는 이 기능을 XML transformation 루틴에 광범위하게 사용한다.
Such use of closures is actually much less than what people in the Lisp and functional programming worlds do. 
But even with my limited uses I miss them a lot when programming in languages without them.
They are one of those things that seem minor when you first come across them, but you quickly grow to like them.
Other languages: C# | Python | Boo | Lisp | JavaScript
Neal Gafter has an excellent posting on the history of closures. 
Vadim Nasardinov led me to this interesting tidbit of history of closures in Java from Guy Steele.
 
Funtional Programming
Functional Style in C++: Closures, Late Binding, and Lambda Abstractions
Closure In wikipedia

[출처] Closure|작성자 황제펭귄

AND