请在 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对于坚持下来的人有回报,一旦配置了命名空间,它就会变得很有趣。

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)和(main)

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

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

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

[ed] 我注意到你正在遵循CFTBT。这是你第一次使用Emacs吗?如果是这样,一个更简单的编辑器/设置可能更好,这样你就可以同时学习clojure和emacs了......(我说的是作为emacs用户,特别是spacemacs与默认的clojure层和轻量级定制......)。

...