ClojureScript로 dom element를 조작하는 로직을 작성하다 element에 대한 변경이 제대로 이루어지지 않는 케이스를 마주했다. 결론적으로 clojure의 지연평가 특성 때문에 발생한 현상이었다.
예를 들어 div 요소에 자식 요소로 많은 span 요소가 존재하는 상황에서 span 요소를 일괄적으로 변경하고 div 요소의 특성을 span 요소를 참조하여 갱신하는 로직을 짠다고 해보자
(defn change-a-span [span] ...)
(defn change-many-span [spans] (map change-a-span spans))
(defn change-something-in [div]
...div의 자식 span 요소에 따라 div의 특성을 변경하는 로직)
(defn update-div [div]
(change-many-span (get-children-spans div)) - (1)
(change-something-in div)) - (2)
위 코드에서 update-div 함수를 평가했을 때, (1)의 change-many-span이 평가된다고 해서, 함수의 결과값이 map (Lazy sequence를 생산한다.) 함수의 결과값이므로 change-a-span이 즉각적으로 평가되는 것이 아니다. 따라서 (2)는 (1)에서 의도한 바가 적용되지 않은 상태에서 진행되어 원치 않는 결과가 나타날 수 있다.
그래서 방법은 굳이 필요하지 않은 곳에 map 등 lazy sequence를 생산하는 함수를 사용하지 않거나, doall로 감싸주는 것이 필요하다.