REPL을 다시 시작하지 않고 Clojure 파일에 정의 된 기능을 다시로드하는 기본 방법은 무엇입니까? 지금 업데이트 된 파일을 사용하려면 다음을 수행해야합니다.
- 편집하다
src/foo/bar.clj
- REPL을 닫으십시오
- REPL을여십시오
(load-file "src/foo/bar.clj")
(use 'foo.bar)
또한 (use 'foo.bar :reload-all)
소스가 전혀 변경되지 않은 것처럼 동작하는 대신 수정 된 함수 본문을 평가하고 새 값을 반환하는 필수 효과가 없습니다.
선적 서류 비치:
답변
또는
(use 'your.namespace :reload)
답변
tools.namespace를 사용하는 것과 같은 대안도 있지만 매우 효율적입니다.
user=> (use '[clojure.tools.namespace.repl :only (refresh)])
user=> (refresh)
:reloading (namespace.app)
:ok
답변
사용 Clojure의 코드를 다시로드 (require … :reload)
하고 :reload-all
있습니다 매우 문제 :
서로 의존하는 두 개의 네임 스페이스를 수정하는 경우 컴파일 오류가 발생하지 않도록 올바른 순서로 다시로드해야합니다.
소스 파일에서 정의를 제거한 후 다시로드하면 해당 정의를 여전히 메모리에서 사용할 수 있습니다. 다른 코드가 해당 정의에 의존하는 경우 코드는 계속 작동하지만 다음에 JVM을 다시 시작할 때 중단됩니다.
다시로드 된 네임 스페이스에가 포함되어 있으면
defmulti
관련된 모든defmethod
표현식 도 다시로드해야합니다 .다시로드 된 네임 스페이스에가 포함 된 경우
defprotocol
해당 프로토콜을 구현하는 모든 레코드 또는 유형을 다시로드하고 해당 레코드 / 유형의 기존 인스턴스를 새 인스턴스로 바꿔야합니다.다시로드 된 네임 스페이스에 매크로가 포함 된 경우 해당 매크로를 사용하는 네임 스페이스도 다시로드해야합니다.
실행중인 프로그램에 다시로드 된 네임 스페이스의 값을 닫는 함수가 포함 된 경우 해당 닫은 값은 업데이트되지 않습니다. 이것은 “핸들러 스택”을 함수 구성으로 구성하는 웹 애플리케이션에서 일반적입니다.
clojure.tools.namespace 라이브러리는 상황을 크게 개선합니다. 네임 스페이스의 종속성 그래프를 기반으로 스마트 다시로드를 수행하는 간편한 새로 고침 기능을 제공합니다.
myapp.web=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
myapp.web=> (refresh)
:reloading (myapp.web)
:ok
불행하게도 refresh
함수 를 참조한 네임 스페이스가 변경된 경우 두 번째로 다시로드하지 못할 수 있습니다. 이는 tools.namespace가 새 코드를로드하기 전에 현재 버전의 네임 스페이스를 삭제하기 때문입니다.
myapp.web=> (refresh)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: refresh in this context, compiling:(/private/var/folders/ks/d6qbfg2s6l1bcg6ws_6bq4600000gn/T/form-init819543191440017519.clj:1:1)
이 문제에 대한 해결 방법으로 정규화 된 var 이름을 사용할 수 있지만 개인적으로 각 새로 고칠 때마다 입력하지 않아도됩니다. 위의 또 다른 문제는 (같은 주요 네임 스페이스를 표준 REPL 도우미 기능을 다시로드 후이다 doc
와 source
) 더 이상이 참조되지 않습니다.
이러한 문제를 해결하기 위해 사용자 네임 스페이스에 대한 실제 소스 파일을 작성하여 안정적으로 다시로드 할 수 있습니다. 소스 파일을 넣었 ~/.lein/src/user.clj
지만 어디에나 배치 할 수 있습니다. 파일은 다음과 같이 최상위 ns 선언에 refresh 함수가 필요합니다.
(ns user
(:require [clojure.tools.namespace.repl :refer [refresh]]))
파일을 넣은 위치가 클래스 경로에 추가되도록 leiningen 사용자 프로파일 을 설정할 수 있습니다 ~/.lein/profiles.clj
. 프로필은 다음과 같아야합니다.
{:user {:dependencies [[org.clojure/tools.namespace "0.2.7"]]
:repl-options { :init-ns user }
:source-paths ["/Users/me/.lein/src"]}}
REPL을 시작할 때 사용자 네임 스페이스를 진입 점으로 설정했습니다. 이렇게하면 REPL 헬퍼 함수가 애플리케이션의 기본 네임 스페이스 대신 사용자 네임 스페이스에서 참조됩니다. 그렇게하면 방금 만든 소스 파일을 변경하지 않으면 손실되지 않습니다.
도움이 되었기를 바랍니다!
답변
가장 좋은 대답은 다음과 같습니다.
(require 'my.namespace :reload-all)
지정된 네임 스페이스를 다시로드 할뿐만 아니라 모든 종속 네임 스페이스도 다시로드합니다.
선적 서류 비치:
답변
papachan의 답변을 기반으로 한 라이너 :
(clojure.tools.namespace.repl/refresh)
답변
나는 이것을 Lighttable (그리고 멋진 instarepl)에서 사용하지만 다른 개발 도구에서 사용해야합니다. 나는 다시로드 한 후에 함수와 멀티 메쏘드의 오래된 정의에 대해 같은 문제를 겪고 있었으므로 개발 중에 네임 스페이스를 선언하는 대신 개발 중에 지금 :
(ns my.namespace)
다음과 같이 네임 스페이스를 선언합니다.
(clojure.core/let [s 'my.namespace]
(clojure.core/remove-ns s)
(clojure.core/in-ns s)
(clojure.core/require '[clojure.core])
(clojure.core/refer 'clojure.core))
꽤 추악하지만 전체 네임 스페이스 (Cmd-Shift-Enter를 Lighttable에서 각 표현식의 새로운 별표 결과를 얻음)를 다시 평가할 때마다 오래된 정의가 모두 사라지고 깨끗한 환경이됩니다. 나는 이것을하기 전에 오래된 정의에 의해 며칠마다 걸려 넘어졌고 그것은 내 정신을 구했습니다. 🙂
답변
파일로드를 다시 시도 하시겠습니까?
IDE를 사용하는 경우 일반적으로 코드 블록을 REPL에 전송하는 키보드 단축키가 있으므로 관련 기능을 효과적으로 재정의 할 수 있습니다.