Header

  1. View current page

    재선아빠님의 노트

Profile_image?t=1224119607&type=big
11

Closures

마틴 파울러

요약하자면, 클로저는 argument 로 function call 을 전달할 수 있는 코드 덩어리이다.

  • public static IList Managers(IList emps){
    IList result = new ArrayList();
    foreach(Employee e in emps)
    if (e.IsManager) result.Add(e);
    return result;
    convert with closures (ruby)
    def managers(emps)
    return emps.select{|e| e.isManager}
    end

참고) select 는 루비의 컬렉션 클래스의 메소드로서 argument 로 클로저나 코드 블록을 받을 수 있다.

위와 같은 구현은 C 언어에서는 함수 포인터나 자바 언어에서는 이너클래스로 해결할 수 있을 수도 있다 하지만 클로저와는 몇가지 다른점이 있다.

차이점 첫번째 : 형식의 차이

클로저는 변수가 정의되는 단계에서 참조가 가능하다.

  • def highPaid(emps)
    threshold = 150
    return emps.select {|e| e.salary > threshold}
    end

위에서 보는 것 처럼 select 블록에서 로컬 변수인 threshold 를 참조하고 있다.

  • def paidMore(amount)
    return Proc.new{|e| e.salary > amount}
    end

이경우는 클로저를 리턴하는 함수이다. 여기서 리턴되는 클로저의 동작은 argument 가 보내지는 것에 따라서 달라진다.

  • highPaid = paidMore(150)  # salary 가 150 이 넘는지 테스트 하는 코드.

    john = Employee.new
    john.salary = 200
    print highPaid.call(john) # 이 코드는 e.salary > amount 라는 코드를 호출한다.

즉, 클로저는 단순히 코드의 덩어리일 뿐만아니라 거기에 더해서 그 클로저가 오게된 환경과도 바인딩되는 점이 중요하다고 할 수 있다.

두번째 차이 : 코드 형식의 단순함

일반적인 코드 형식보다도 단순하게 정의할 수 있다. - 복잡하지 않은 문법.

파울러는 이 사소한 차이가 가장 중요한 차이라고 말하고 있다. 얼마나 자주 사용하게 될 것이며, 사용하지 못할때 얼마나 아쉬워할 것인지에 대해서 언급하고 있다.

  • File.open(filename) {|f| doSomethingWithFile(f)}

뭔가? 위 코드가 의미하는 것은? --> 파일을 열고 처리하고 파일을 닫는 과정을 나타낸다.

대부분의 언어에서 파일을 가지고 다룰때 주의할 점은 파일을 열고 닫는 것이다. 파일 오퍼레이션을 하기 위해서 열어두고 제대로 닫지 않는 경우에는 문제가 생길 수 있다. (물론 예외 같은 상황이 발생했을 때는 더욱이나)

그러나 위와 같이 파일 오퍼레이션을 코드 블록(클로저)로 할 경우, 아주 쉽게 트랜젝션을 다룰 수 있다는 것이다.

개념 1

클로저의 개념을 자바스크립트를 중심으로 이해해본다.

클로저는 개념 자체를 이해하는 것은 그리 어렵지 않지만(개념은 단순하다) 왠지 모르게 설명을 해놓은 다른 자료들을 보면 어렵게 느껴지고 복잡하게 느껴진다. 어쨌든 예제를 중심으로 개념을 파악하는데 주력해 보기로 하자.

Example :

function sayHello(name){
var text = 'Hello " + name;
var sayAlert = function() { alert(text); }
sayAlert();
}

sayHello('Bob');

정리 첫번째

  1. 클로저는 function 의 로컬 변수이다. - 위 예제코드에서 보면 function 이 리턴될때 까지 그 생명주기가 이어진다.
  2. 클로저는 functoin 이 리턴될때 까지 메모리에서 제거되지 않는다.

Example2 :

function sayHello2(name){
var text = 'Hello ' + name; //local variable
var sayAlert = function() { alert(text); }
return sayAlert;
}

var say2 = sayHello2('Jane');
say2();

위에서는 say2 와 sayAlert 간에 reference 가 생긴 것 이라고 생각하면 된다. 이런 식으로 function 안에 이름이 없는 function 인 function() { alert(text); } 와 같은 형태의 function 을 선언하게 되면 functoin sayHello2 는 클로저를 가지게 되는 것이다.

정리 두번째

  1. functoin 내부에서 function 이라는 키워드를 사용하게 되면 클로저를 생성하게 된다.
  2. function 내부에 function 을 선언한 경우 외부 function 이 호출될 때 마다 내부의 function 이 재생성 된다. (매번 생성)

Example3 :

function sayAlice() {
var sayAlert = function() { alert(alice)' }
var alice = 'Hello Alice';
return sayAlert;
}

정리 세번째

  1. sayAlice 라는 function에서 내부에 존재하는 클로저는 alice 라는 로컬 변수를 참조하고 있다. 하지만 클로저가 먼저 선언되고 변수가 나중에 선언되더라도 오류가 발생하지는 않는다. - 클로저 내부에서는 클로저가 선언된 function 의 로컬 변수들을 언제든지 접근할 수 있다는 의미

종합정리

  1. function 내부에서 function 키워드를 사용하면 클로저가 선언되는 것이다.
  2. function 내부에서 eval() 을 사용할 때 마다 클로저가 사용되는 것이다. eval 내부 에서는 function 의 로컬 변수를 참조할 수 있고 새로운 변수를 생성할 수도 있다.
  3. new Function 같은 Function 이라는 키워드를 function 내부에서 사용하면 이경우에는 클로저를 생성하지 않게된다. 따라서 로컬 변수를 참조할 수도 없다.

개념2

  • 블록은 기본적으로 이름없는 function 이다.
  • 블록은 루프문의 축약을 위해서 디자인 되었다.
  • 클 로저 오브젝트는 실행가능한 코드를 포함할 수 있고, 로컬 변수들을 접근할 수 있다. 또한 function 이 return 될 경우 로컬 스코프는 destroy 되고 로컬 변수는 클로저 오브젝트의 일부로 남아있게 된다. 더이상의 참조가 존재하지 않게 되면 GC 되면서 로컬변수도 사라지게된다.

History

Last edited on 03/14/2007 17:02 by JasonPA

Comments (0)

You must log in to leave a comment. Please sign in.