在交互式开发过程中使用 clojure.repl 函数的最佳实践是什么?

What is the best practice for using clojure.repl functions during interacitve development?

我经常发现自己在处理 clojure 源代码时反复键入 (ns user) 并按 C+c M+n代码。问题是我经常使用像 sourcedoc 这样的函数,它们在 clojure.repl 中,我不想 :require 它们到我的命名空间。在这种情况下,经验丰富的 clojurians 在做什么?

澄清:我知道 clojure 的命名空间是如何工作的。我想要实现的是能够调用 (source myfunc)(doc myfunc) 等,而无需在 REPL 中使用完全限定的名称,而无需在我的每个命名空间中都需要来自 clojure.repl 的函数。

感谢您澄清您的问题。

Leiningen 有一个名为 :injections 的功能,您可以 combine with vinyasa 获得此效果 如果您在 leiningen 个人资料中添加类似内容:

~/lein/profiles.clj:

{:user {:plugins []
        :dependencies [[im.chit/vinyasa "0.1.8"]]
        :injections [(require 'vinyasa.inject)
                      (vinyasa.inject/inject
                       'clojure.core '>
                       '[[clojure.repl doc source]
                         [clojure.pprint pprint pp]])]}}

因为这在您的 profiles.clj 中,它只会影响您。在该项目上工作的其他人不会受到影响。


因为注入 clojure.core 让我觉得有点不确定,所以我听从了 vinyasa 作者的建议,注入了一个名为 .这是我为我从事的每个项目创建的个人资料。该名称空间始终存在,这使得这些功能即使在尚未引用 clojure.core.

的新创建的名称空间中也能正常工作

我的~/.lein/profiles.clj:

{:user
  {:plugins []
   :dependencies [[spyscope "0.1.4"]
                  [org.clojure/tools.namespace "0.2.4"]
                  [io.aviso/pretty "0.1.8"]
                  [im.chit/vinyasa "0.4.7"]]
   :injections
   [(require 'spyscope.core)
    (require '[vinyasa.inject :as inject])
    (require 'io.aviso.repl)
    (inject/in ;; the default injected namespace is `.`

               ;; note that `:refer, :all and :exclude can be used
               [vinyasa.inject :refer [inject [in inject-in]]]
               [clojure.pprint :refer [pprint]]
               [clojure.java.shell :refer [sh]]
               [clojure.repl :refer [doc source]]
               [vinyasa.maven pull]
               [vinyasa.reflection .> .? .* .% .%> .& .>ns .>var])]}}

工作方式如下:

hello.core> (./doc first)
-------------------------
clojure.core/first
([coll])
  Returns the first item in the collection. Calls seq on its
    argument. If coll is nil, returns nil.
nil
hello.core> (in-ns 'new-namespace)
#namespace[new-namespace]
new-namespace> (./doc first)
nil
new-namespace> (clojure.core/refer-clojure)
nil
new-namespace> (./doc first)
-------------------------
clojure.core/first
([coll])
  Returns the first item in the collection. Calls seq on its
    argument. If coll is nil, returns nil.
nil

为此,您可以使用 vinyasa library, in particular its inject 功能。基本上,您需要将所需的函数从 clojure.repl 命名空间添加到 clojure.core 命名空间。在您不需要明确要求它们之后。请参阅以下内容:

user> (require '[vinyasa.inject :refer [inject]])
nil

;; injecting `source` and `doc` symbols to clojure.core
user> (inject '[clojure.core [clojure.repl source doc]]) 
[]

;; switching to some other namespace
user> (require 'my-project.core)
nil
user> (in-ns 'my-project.core)
#namespace[my-project.core]

;; now those functions are accessible w/o qualifier
my-project.core> (doc vector) 
-------------------------
clojure.core/vector
([] [a] [a b] [a b c] [a b c d] [a b c d e] [a b c d e f] [a b c d e f & args])
  Creates a new vector containing the args.
nil