let
바인딩을 구현하는 2 가지 방법을 볼 수 있습니다. 먼저, SICP으로부터 알려진 바와 같이, let
은 람다 함수으로 구현 될 수있다. 이것은 편리하고 간단하지만 각 람다 (fn
)가 JVM에서 별도의 클래스로 변환되고 평균 프로그램에서 let
의 수가 사용된다는 사실을 고려하면 매우 비싸 보입니다.Clojure에서`let '을 구현하는 방법과 그 오버 헤드는 무엇입니까?
두 번째로, let
바인딩은 로컬 Java 변수으로 직접 변환 될 수 있습니다. 오버 헤드는 거의 발생하지 않지만 스택에 바인딩을 저장하면 언어 의미가 깨집니다.이 경우 클로저 생성은 불가능합니다. 저장된 값은 스택을 푸는 즉시 삭제됩니다.
그래서 Clojure에서 실제로 사용되는 구현은 무엇입니까? Clojure 소스의 해당 줄을 가리키는 것이 좋습니다.
그래서 필요한 경우에만 클로저 객체가 생성되고 (그리고 최종 변수가 복사 됨) 단순한 경우에 대해 vars가 스택에만 머물러 있다고 생각합니까? – ffriend
예, 그것이 작동하는 방식은 거의 같습니다. 관심이 있으시면 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java를 방문하십시오. (Clojure의 컴파일러가하고있는 "마술"이 많이 있습니다.) – mikera
@ffriend Java는 메소드 범위와는 달리 블록 범위 변수를 가지고 있습니다. 나는 Clojure 컴파일러가하는 것을 보지 않았지만, * let *은 최종 변수를 포함하는 코드 블록에 의해 간단하게 구현 될 수 있다고 생각한다. 왜 폐쇄로 구현 될 것이라고 생각하는지 모르겠습니다. –