Clojure的import与:import有何区别?

5
阅读Clojure API的导入部分,我发现ns宏中的:import优先于import使用。然而,当我使用swank/slime/emacs编码时,我无法将(ns...)s表达式c-x c-e到repl中获取依赖项,但是使用(import ...)可以。为什么要优先选择:import而不是import?是否有一种快速的方法可以从我的.clj文件中的(ns...)s表达式中导入依赖项到repl中?(相同的问题也适用于:use和:refer..感谢)
4个回答

5
这是我的首选工作流程:
  • 启动Swank/Slime
  • 在Emacs中打开要处理的文件
  • 按下C-c C-k编译并加载相关文件
  • 按下,,然后按i,输入你正在操作的命名空间名称并按下Enter
现在你的Slime REPL应该在你正在操作的命名空间中,你可以在顶部添加到ns声明,并在更改时使用C-c C-k(包括ns导入)。

你最后一个要点我有点不太清楚。你是在文件中输入“,”吗?那不会只是插入逗号和字母“i”吗? - ftravers
当您的光标位于Slime REPL缓冲区中,在提示符处未键入任何其他内容之前,请键入“`”字符。这将使文本“Command:”出现在迷你缓冲区中。现在立即键入“i”,您将看到文本“Package:”出现在迷你缓冲区中。现在开始键入您的软件包名称,如有需要,请使用制表符自动补全,直到完整的命名空间名称出现在迷你缓冲区中。按下“ENTER”键,您的Slime REPL现在将进入您的目标命名空间。 - semperos

2

(ns ...)形式更受青睐,因为它可以使你的代码更易读。所有命名空间声明将被收集在文件的顶部。在像Java这样的语言中,编译器会执行此操作。而且,包含宏ns消除了引用符号的需要。use、import、refer等也是如此。

我认为C-x C-e快捷键将发送代码片段到连接的Swank服务器,并对其进行评估。例如,如下表达式:

(ns my.test
   (:require [clojure.contrib.logging :as log])
   (:import [java.io File]))

将会创建一个名为my.test的新命名空间,其中包括contrib日志记录和java.io文件。它不会更改repl的命名空间。要更改命名空间,请从您正在编辑的文件中按C-c M-p,然后会提示您切换到该文件的命名空间的名称(除非您已经在该命名空间中)。按Enter键选择。 C-c C-z应该切换到repl。现在,您将看到 my.test => 而不是 user =>提示,表示您在该命名空间中。

我设置的工作流是在保存时编译整个文件,使用:

(defun ed/clojure-compile-on-save (&optional args)
  "Compile with slime on save"
  (interactive)
  (if (and (eq major-mode 'clojure-mode)
      (slime-connected-p))
      (slime-compile-and-load-file)))
(add-hook 'after-save-hook 'ed/clojure-compile-on-save)

这样一来,每当我保存文件时,它都会被编译并由Swank服务器加载,我可以在命名空间中使用REPL进行实验。


2

我不确定为什么 c-x c-e 无法工作,但只要命名空间已经存在,ns 表达式上的 C-c C-c 就可以正确工作。


1

:在ns声明中的import是首选,因为它将与命名空间相关的所有内容放在一个地方,通常在文件顶部。这是良好的编码实践。

我认为解析ns声明C-x C-e无法工作是SLIME工作方式的一部分。当您评估一个sexp时,SLIME会在当前命名空间中执行它。因此,评估(import 'java.io.File)将导入File到目前包含在ns中的任何命名空间。

评估(ns my.namespace (:import java.io.File)声明确实修改了声明中指定的命名空间,但它不会改变ns的值。除非您使用(in-ns'my.namespace)更改到该命名空间,否则您将看不到导入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接