본문 바로가기
Lang & Framework/Language

Closure

by . 2021. 2. 10.

Closure

내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것. 자신의 영역 밖(외부함수)에서 호출된 함수의 변수값과 레퍼런스를 복사, 저장해 (내부에서) 이 값들에 접근할수 있게 해준다. 일급 함수를 지원하는 언어에서 *네임 바인딩 기술. 일급 함수를 지원하는 언어의 네임 바인딩 기술. 클로저는 어떤 함수를 함수 자신이 가지고 있는 환경과 함께 저장한 레코드이다. 또한 함수가 가진 프리변수(free variable)를 클로저가 만들어지는 당시의 값과 레퍼런스에 맵핑해준다. 자바는 클로저를 지원하지 않는다. 

 

 

A closure is a nested function which has access to a free variable from an enclosing function that has finished its execution. 

A closure is a block of code that can be referenced (and passed around) with access to the variables of the enclosing scope. A closure gives you access to an outer function’s scope from an inner function

 

 

 

Free variable(자유변수)

코드블럭안에서 사용 되었지만, 그 코드블럭안에서 정의되지 않은 변수.

외부 범위의 변수를 함수 내부로 바인딩하는 기술입니다. 클로저는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 뜻한다. 그 뜻은 외부 함수안에 있는 내부 함수가 외부함수의 지역변수를 사용할 수 있다라는 뜻이다. 외부 함수가 종료 되어도 값은 유지 된다.

바깥으로 내보내고 문 닫아버리는거. 마무리 투수.

// 외부함수
def outer():
    language = "Python"
	
    
    // 내부함수
    def inner():
    	
        // 외부함수 language의 값 Python을 기억한다.
        print(f'{language}. Hello!')
        
        
    // 외부함수의 return 값이 내부함수를 호출    
    return inner()


print(outer())



<그림1> closure / free variable

 

Here variable a is defined in the scope of outer() function. If we look at inner() function, a is not defined there. But, function inner() is using variable a and hence variable a in inner() function is Free Variable.

language는 outer 안에 포함된 지역변수이며 inner. 하지만 inner 함수에서. 이를 Free Variable(자유변수)라고 부른다.

 

 

 

def name_decorator(param):
    print('외부함수 영역')
    def inner():
        print('내부함수 영역')
        return param()
    return inner()

def greeting():
  return "Hello"

print(name_decorator(greeting))

print('dd')

 

# 클로저 : 값을 기억한다. scope가 닫혀도 안에 선언된 함수들을 기억하고 있다.
# 서버프로그램 -> 동시성(Concurrency) 제어 - 한정된 메모리 공간에 여러 자원이 접근하기 때문에 교착상태(Dead lock)
# 메모리를 공유하지 않고 메시지 전달로 처리하기 위한 Erlang
# 클로저는 공유하되 변경되지 않는(Immutable, Read Only) -> 함수형 프로그래밍
# 클로저는 불변자료구조 및 atom, STM -> 멀티스레드(Coroutine) 프로그래밍에 강점 : 불변상태를 기억한다.
a = 100
print(a+10)
print(a+100)


# 클래스 이용
class Averager() :
    def __init__(self):
        self._seires = []


    def __call__(self, v):
        self._seires.append(v)
        print("inner >> {}/{}".format(self._seires, len(self._seires)))
        
    return sum(self._seires)/len(self._seires)

averager_cls = Averager()
print(dir(averager_cls))


# 누적 : 자유영역에 대한 함수의 scope를 기억하고 있다. 즉, 상태를 기억하고 있다.
print(averager_cls(10))
print(averager_cls(30))
print(averager_cls(50))

 

 

 

 

 

 

사용 이유

정보의 은닉. 캡슐화를 위함.

 

어떤 경우에 이것을 쓸까? 이 함수 안에서만 사용되는 함수. 함수 바깥쪽에 선언하면 응집성이 떨어진다. 다른 곳에서 간섭을 적게 받겠지? 내부, 외부함수. 

var = 외부함수에 선언된 지역변수라고 한다.

내부함수는 외부함수의 지역변수에 접근할 수 있다. 외부 함수가 더 이상 사용되지 않는 경우에도 내부함수가 외부함수에 접근할 수 있다.

 

 

When and why to use Closures

1.클로저가 콜백함수

  1. As closures are used as callback functions, they provide some sort of data hiding. This helps us to reduce the use of global variables.
  2. When we have few functions in our code, closures prove to be efficient way. But if we need to have many functions, then go for class (OOP).

 

 

function outter(){
var title = "coding everybody";
return function(){
alert(title);
}
}
inner = outter();
inner();

 

 

 

 

* first-class function(일급 함수) : 함수를 일급객체로 취급하는 함수. 일급객체는 아래의 조건을 만족한다.

  • 함수를 변수/자료구조로 할당할 수 있다.
  • 함수를 인자(매개변수)로 전달할 수 있다.
  • 함수의 반환 값(return 값)으로 함수를 전달할 수 있다.

 

 

free variable(프리변수)

 

 

# 클로저 : 값을 기억한다. scope가 닫혀도 안에 선언된 함수들을 기억하고 있다.
# 서버프로그램 -> 동시성(Concurrency) 제어 - 한정된 메모리 공간에 여러 자원이 접근하기 때문에 교착상태(Dead lock)
# 메모리를 공유하지 않고 메시지 전달로 처리하기 위한 Erlang
# 클로저는 공유하되 변경되지 않는(Immutable, Read Only) -> 함수형 프로그래밍
# 클로저는 불변자료구조 및 atom, STM -> 멀티스레드(Coroutine) 프로그래밍에 강점 : 불변상태를 기억한다.
a = 100
print(a+10)
print(a+100)


# 클래스 이용
class Averager() :
    def __init__(self):
        self._seires = []


    def __call__(self, v):
        self._seires.append(v)
        print("inner >> {}/{}".format(self._seires, len(self._seires)))
        
    return sum(self._seires)/len(self._seires)

averager_cls = Averager()
print(dir(averager_cls))


# 누적 : 자유영역에 대한 함수의 scope를 기억하고 있다. 즉, 상태를 기억하고 있다.
print(averager_cls(10))
print(averager_cls(30))
print(averager_cls(50))

 

 


 

dir() 명령어로 함수를 들여다보자. 

print(dir(outer_func))

 

 

 

 


Reference

en.wikipedia.org/wiki/Name_binding

 

Name binding - Wikipedia

In programming languages, name binding is the association of entities (data and/or code) with identifiers.[1] An identifier bound to an object is said to reference that object. Machine languages have no built-in notion of identifiers, but name-object bindi

en.wikipedia.org

medium.com/sjk5766/javascript-closure%EB%8A%94-%EC%99%9C-%EC%93%B8%EA%B9%8C-81bcdef6352

 

JavaScript Closure는 왜 쓸까?

쬐끔 알고 있던 Closure를 최근에 좀 더 알게 되었고, 음.. 근데 언제? 무슨 이유로 개발할 때 Closure를 쓸까 궁금해서 찾아보게 되었습니다. 검색해서 찾은 여러 글 들 중에 고개를 끄덕거린 답변을

medium.com

 

'Lang & Framework > Language' 카테고리의 다른 글

Comparator  (0) 2021.01.25