请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

+1 投票
工具

按照这个指南尝试运行我的第一个Clojure程序时遇到问题。

以下是我的基本代码

(ns clojure-noob.core
  (:gen-class))

(defn -main
  "I don't do a whole lot...yet."
  [& args]
(println "Hello, World!"))

(defn train
  []
  (println "Choo choo!")) 

以下是在切换命名空间后得到的结果

clojure-noob.core> (train)

Syntax error compiling at (*cider-repl Clojure/Projects:localhost:49632(clj)*:46:20).
Unable to resolve symbol: train in this context
clojure-noob.core> (-main)
Syntax error compiling at (*cider-repl Clojure/Projects:localhost:49632(clj)*:49:20).
Unable to resolve symbol: -main in this context
clojure-noob.core> 

我遗漏了哪一步?

为什么学习曲线如此陡峭?

3 个回答

+1 投票

很可能是你在切换到命名空间,但代码没有被先评估。你在正确的命名空间但它是空的

所以如果你在一个shell中并且用类似下面的内容打开REPL

$ pwd
/home/whoever/programming-clojure
$ tree
.
└── clojure_noob
    └── core.clj

1 directory, 1 file

$ clj
Clojure 1.10.3
user=> (ns clojure-noob.core)
nil

clojure-noob.core=> (train)
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: train in this context

clojure-noob.core=> (require 'clojure-noob.core) ;; try to load code'
Execution error (FileNotFoundException) at user/eval4 (REPL:1).
Could not locate clojure_noob/core__init.class, clojure_noob/core.clj or clojure_noob/core.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.

clojure-noob.core=> (System/exit 0) ;; That did not work
$ mkdir src
$ mv clojure_noob/ src/
$ clj
user=> (ns clojure-noob.core)
nil
clojure-noob.core=> (require 'clojure-noob.core) ;;' ask.clojure syntax
nil
clojure-noob.core=> (train)
Choo choo!
nil

那是什么意思?

  1. Clojure已经初始化。已加载clojure.core命名空间,加载了user命名空间以及引用了核心函数。

  2. 切换到clojure-noob.core命名空间。clojure.core命名空间默认引用(以及一些其他东西 - https://clojure.org/reference/namespaces)。但Clojure甚至还没尝试读取clojure_noob/core.clj文件。

  3. 尝试用require将函数读入clojure-noob.core命名空间。我们遇到了Clojure的经典问题 - 它找不到文件。

  4. 我们使用禁止的知识,Clojure将添加到类路径中,但没有添加$PWD。理论上你可以从文档中解决这个问题,但别问我具体在哪里,我从未设法理解人们应该如何解决这个问题。重新整理目录结构。

  5. 现在它正常工作了。

我的无偿建议:在依赖管理出现问题时,直接去ask.clojure.org寻求帮助——自己阅读文档或摸索是非常浪费时间的。这些内容真的很难理解,我花了几个月才渐渐适应。没有哪种语言是完美的。不过,Clojure会给予那些经过考验的人回报,一旦命名空间设置好了,就会变得很有趣。

by
谢谢——我试了这种方法,但最后还是遇到了同样的错误。

让我在匹配您的目录结构后重试。
by
我又试了一次,结果还是一样。

clojure-noob.core=> (train)
在 (REPL:1:1) 编译时出现语法错误。
无法在这个上下文中解析符号: train
by
奇怪。没有足够的信息来准确诊断这里出了什么问题,但你可以尝试以下方法

1] 运行 (map println (all-ns)) 获取已加载命名空间列表。也许存在拼写错误,或者其他原因导致函数被加载到错误的命名空间。

2] 尝试运行 (require 'clojure-noob.core') 以检查Clojure是否能找到相关文件。

3] 运行 (ns-publics 'clojure-noob.core') 来查看在命名空间中定义了哪些符号(如果有)。

这个错误是Clojure中比较简单的错误之一——你当前正处于正确的命名空间,但是(train)并不在那里。这可能是文件没有被找到(这可以通过require调用进行检查),或者存在像拼写错误之类的错误,导致函数在导入过程中丢失。

如果文件能够找到,你将需要通过探索性函数进行一些挖掘,以便有人能够帮助你。就像在https://clojure.org/reference/namespaces
+1 投票

owenRiddy说过的话。

我认为您遗漏的步骤就在指南告诉您编写(train)函数下方,它告诉您重新编译文件

完成之后,保存您的文件,并在REPL会话中使用C-c C-k编译当前文件。(您必须编译代码才能让REPL了解您的更改。)现在如果您在REPL中运行(train),它将返回Choo choo!。

这相当于owenRiddy做的那样

clojure-noob.core=> (require 'clojure-noob.core)

见官方Clojure指南中的命名空间导航,有一些很好的提示。

0

编辑了

使用clj命令行,如果我将您的内容复制/粘贴到repl中

PS C:\Users\joinr> clj
Clojure 1.10.2
user=> (ns clojure-noob.core
         (:gen-class))

(defn -main
  "I don't do a whole lot...yet."
  [& args]
  (println "Hello, World!"))

(defn train
  []
  nil

#'clojure-noob.core/-main
#'clojure-noob.core/train

然后我评估(train)和(main)

clojure-noob.core=> (train)
Choo choo!
nil

clojure-noob.core=> (-main)
Hello, World!
nil

一切都看起来很正常。您做了什么不同的?

[ed] 我注意到您正在遵循CFTBT。这是您第一次使用emacs吗?如果是这样,一个更简单的编辑器/设置可能更好,这样您不必同时学习clojure和emacs....(我说这个是因为我是emacs用户,特别是spacemacs,默认clojure层和最少定制....).

...