Clojure 标记的 literals::Raise 错误 - 没有派发宏

Clojure-tagged literals::Raise an error-No dispatch macro for it

tmp2/src/data_readers.clj

{ct/G tmp2.core/foo}

tmp2/src/tmp2/core.clj

(ns tmp2.core)

(defn foo
  [x]
  (println x "Hello, World!"))

(defn -main
  [& args]

  (println "Hello, World!")
  (foo 123)
  (#ct/G "abc"))

在工程目录下"lein run"时,显示结果"abc Hello, World!",但报错

Caused by: java.lang.RuntimeException: No dispatch macro for: c
        at clojure.lang.Util.runtimeException(Util.java:221)
        at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:851)
        at clojure.lang.LispReader.read(LispReader.java:285)
        at clojure.lang.LispReader.readDelimitedList(LispReader.java:1398)
        at clojure.lang.LispReader$ListReader.invoke(LispReader.java:1243)
        at clojure.lang.LispReader.read(LispReader.java:285)
        at clojure.lang.LispReader.readDelimitedList(LispReader.java:1398)
        at clojure.lang.LispReader$ListReader.invoke(LispReader.java:1243)
        at clojure.lang.LispReader.read(LispReader.java:285)
        at clojure.lang.LispReader.read(LispReader.java:216)
        at clojure.lang.Compiler.load(Compiler.java:7630)

我应该在哪里更改代码?任何帮助将不胜感激

其实这里有两个问题:

1) 你的 foo 函数 returns nil,reader 函数似乎不能 return 字面值 nil。所以你实际上必须 return 来自 foo:

的东西
(defn foo [x]
  (println x "Hello, World!")
  :something)

或者,如果您确实需要在生成的代码中使用 nil,您可以这样做:

(defn foo [x]
  (println x "Hello, World!")
  '(quote nil))

2) 第二个问题是您实际上尝试在此处调用标签应用程序的结果:

(#ct/G "abc")

语法 #tag value 在读取时使用 (tag-fn value) 求值,然后将结果直接放入源代码中。当您使用额外的一对括号时,这就是您的情况:

((foo "abc")) 并且,作为 foo 函数 return foo-return-value,它就变成了 (foo-return-value) ,而这又导致一个错误。

所以,

(defn foo [x]
  (println x "Hello, World!")
  :nothing)

(defn -main
  [& args]
  (println "Hello, World!")
  (foo 123)
  #ct/G "abc")

应该可以工作

好的,成功了。

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test))

(defn foo
  [x]
  (println :foo-reader x)
  x)

(dotest
  (println :test-foo-plain)
  (foo 123)
  (println :test-foo-reader)
  (println #ct/G "abc")
  (println :test-leave))

注意数据读取器文件的位置和内容。它必须位于类路径的根目录中。在这种情况下是 src/clj:

~/expr/demo > cat src/clj/data_readers.clj
{ct/G tst.demo.core/foo}

和测试结果:

> lein test

:foo-reader abc    ; <====== NOTICE!

-------------------------------
   Clojure 1.10.1    Java 14
-------------------------------

:test-foo-plain
:foo-reader 123
:test-foo-reader
abc
:test-leave

请注意,在读取源代码文件、编译或执行测试之前,标记文字的 foo reader 被调用。


关于类路径的根目录

Lein 项目由 projects.clj 中的这些条目控制:

  :source-paths            ["src/clj"]
  :java-source-paths       ["src/java"]
  :test-paths              ["test/clj"]

如果你没有 cljjava 位(一些项目也将 cljccljs 文件分割成单独的目录树),你将需要修改 project.clj 或文件位置。