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添加了src/到类路径中,但并没有添加$PWD。从理论上讲,你可以从文档中解决这个问题,但别问我在哪里,我从未搞清楚人们是如何打算解决的。重新排列目录结构。

  5. 现在它工作正常了。

我的免费建议:当依赖项管理出现问题时,直接去ask.clojure.org寻求帮助——阅读文档或自己解决问题只会浪费时间。这些东西很难弄清楚,我花了数月才习惯。没有哪种语言是完美的。尽管如此,Clojure有时会因其坚韧而有所回报,一旦命名空间设置妥当,就会乐趣无穷。

谢谢——我已经试过了,但结尾处仍然出现同样的错误。

让我在匹配您的目录结构后重试。
我再次尝试,结果相同

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

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) 函数时,它告诉你要重新编译文件。

完成操作后,保存你的文件,并使用 C-c C-k 编译当前 REPL 会话中的文件。(你必须编译你的代码,以便 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

看起来一切正常。你做了什么不同的选择?

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

...