简体   繁体   English

Clojure:异常后如何恢复 REPL?

[英]Clojure: How to restore REPL after exception?

What's the proper workflow in cases when you have an error after you restart/reload your app using mount?使用 mount 重新启动/重新加载应用程序后出现错误时,正确的工作流程是什么?

An example:一个例子:

user> (restart)
#error {
 :cause "Unable to resolve symbol: account-database in this context"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling at (app/model/session.clj:55:39)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 55, :column 39, :source "app/model/session.clj"}
   :at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
  {:type java.lang.RuntimeException
   :message "Unable to resolve symbol: account-database in this context"
   :at [clojure.lang.Util runtimeException "Util.java" 221]}]
 :trace
 [[clojure.lang.Util runtimeException "Util.java" 221]
Reloadable Clojure REPL
user> (restart)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:597:7).
Unable to resolve symbol: restart in this context
user> (start)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:600:7).
Unable to resolve symbol: start in this context

After fixing an error, I can not (restart) this reply anymore due to the following error:修复错误后,由于以下错误,我无法(重新启动)此回复:

Unable to resolve symbol: restart in this context无法解析符号:在此上下文中重新启动

Is it always like this or am I doing something wrong with my REPL workflow?总是这样还是我的 REPL 工作流程有问题?

As a workaround, I cider-quit my REPL session and start it again but that's very annoying.作为一种解决方法,我退出我的 REPL session 并重新启动它,但这很烦人。

It seems I can use mount/start after fixing an error:看来我可以在修复错误后使用 mount/start :

user> (mount/start)
{:started
 ["#'app.server-components.config/config"
  "#'app.model.database/pool"
  "#'app.model.mock-database/conn"]}

But it completely loses my user namespace scope, REPL doesn't see any of its methods + I can't send user namespace to repl because of the following error:但它完全失去了我的用户命名空间 scope,REPL 看不到它的任何方法 + 由于以下错误,我无法将用户命名空间发送到 repl:

Syntax error compiling at (app/server_components/pathom.clj:1:1).
namespace 'app.model.session' not found
("src/main" "src/dev" "src/test")#function[expound.alpha/printer]nil#'user/start#'user/stop#'user/restartnil


That's what my user namespace looks like:这就是我的用户命名空间的样子:

(ns user
  (:require
    [clojure.tools.namespace.repl :as tools-ns :refer [set-refresh-dirs]]
    [expound.alpha :as expound]
    [clojure.spec.alpha :as s]
    [mount.core :as mount]
    ;; this is the top-level dependent component...mount will find the rest via ns requires
    [app.server-components.http-server :refer [http-server]]))

;; ==================== SERVER ====================
(set-refresh-dirs "src/main" "src/dev" "src/test")
;; Change the default output of spec to be more readable
(alter-var-root #'s/*explain-out* (constantly expound/printer))

(defn start
  "Start the web server"
  [] (mount/start))

(defn stop
  "Stop the web server"
  [] (mount/stop))

(defn restart
  "Stop, reload code, and restart the server. If there is a compile error, use:

  (tools-ns/refresh)

  to recompile, and then use `start` once things are good."
  []
  (stop)
  (tools-ns/refresh :after 'user/start))

Here's the workaround that seems to work in case of an error:这是在出现错误时似乎可行的解决方法:

  1. the content of a fixed file need to be sent to the REPL需要将固定文件的内容发送到 REPL
  2. switch back to user namespace切换回user命名空间
  3. send the content of your user namespace to the REPLuser命名空间的内容发送到 REPL
  4. there is no 4 - you just got your REPL back.没有 4 - 你刚拿回你的 REPL。

At this point you can use your regular (start) , (stop) , (restart) .此时您可以使用常规的(start)(stop)(restart)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM