【问题标题】:What is the best practice for using clojure.repl functions during interacitve development?在交互式开发期间使用 clojure.repl 函数的最佳实践是什么?
【发布时间】:2016-07-07 18:14:45
【问题描述】:

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

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

【问题讨论】:

  • my workflow 中,我喜欢保留一个单独的源文件来保存我的user 命名空间及其所有依赖项。例如,当我不使用Component 时,我的dev/user.clj 文件的内容通常如下所示:(ns user (:require [clojure.pprint :refer [pprint]] [clojure.repl :refer [doc source]]))
  • 你提到了C-c M-n。如果你在 Emacs 中使用 CIDER,M-. 相当于source。还有C-d d ddoc。您无需输入 myfunc,因为该点已在该文本上。

标签: emacs clojure read-eval-print-loop cider


【解决方案1】:

感谢您澄清您的要求。

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

【讨论】:

    【解决方案2】:

    为此,您可以使用vinyasa 库,尤其是它的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
    

    【讨论】:

      猜你喜欢
      • 2010-10-08
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-21
      相关资源
      最近更新 更多