이미 알고 있듯이 Clojure에서 가변성이 권장되지 않는다고해서 이것이 금지되어 있고이를 지원하는 구조가 없다는 의미는 아닙니다. 따라서 def
다른 언어에서 할당하는 것과 비슷한 방식으로 환경에서 바인딩을 변경하거나 변경할 수 있습니다 ( vars의 Clojure 설명서 참조 ). 글로벌 환경에서 바인딩을 변경하면 이러한 바인딩을 사용하는 데이터 오브젝트도 변경됩니다. 예를 들면 다음과 같습니다.
user=> (def x 1)
#'user/x
user=> (defn f [y] (+ x y))
#'user/f
user=> (f 1)
2
user=> (def x 100)
#'user/x
user=> (f 1)
101
에 대한 바인딩을 재정의 한 후 본문에서 해당 바인딩을 사용하므로 x
함수 f
도 변경되었습니다.
변수를 재정의해도 기존 바인딩이 삭제되지 않고 그림자 만 표시되는 언어와 비교해보십시오 . 즉, 새 정의 다음에 오는 범위에서는 보이지 않습니다. SML REPL에서 동일한 코드를 작성하면 어떻게되는지 확인하십시오.
- val x = 1;
val x = 1 : int
- fun f y = x + y;
val f = fn : int -> int
- f 1;
val it = 2 : int
- val x = 100;
val x = 100 : int
- f 1;
val it = 2 : int
의 두 번째 정의 후에도 x
함수 는 정의 될 때 범위에 f
있던 바인딩 x = 1
을 계속 사용합니다 . 즉, 바인딩 val x = 100
이 이전 바인딩을 겹쳐 쓰지 않습니다 val x = 1
.
결론 : Clojure를 사용하면 글로벌 환경을 변경하고 바인딩을 재정의 할 수 있습니다. SML과 같은 다른 언어와 마찬가지로 이것을 피할 수는 있지만 def
Clojure 의 구문은 글로벌 환경에 액세스하고 변경하는 것을 의미합니다. 실제로 이것은 Java, C ++, Python과 같은 명령형 언어에서 할당이 할 수있는 것과 매우 유사합니다.
그럼에도 불구하고 Clojure는 돌연변이를 피하는 많은 구성과 라이브러리를 제공하며 전혀 사용하지 않고도 먼 길을 갈 수 있습니다. 돌연변이를 피하는 것은 Clojure에서 선호되는 프로그래밍 스타일입니다.