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

当您完成时,保存您的文件并使用 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)和(macmain)

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

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

似乎一切正常。你的不同之处在哪里?

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

...