Литералы с тегами Clojure :: Вызовите макрос ошибки-Нет для него - PullRequest
0 голосов
/ 26 апреля 2020

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" в каталоге проекта, он показывает результат "ab c 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)

Где мне изменить код? Любая помощь будет оценена

Ответы [ 2 ]

0 голосов
/ 26 апреля 2020

ОК, все заработало.

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

Обратите внимание на расположение и содержимое файла Data Readers. Это должно быть на ROOT пути к классам. В этом случае это 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 для помеченного литерала был вызван, когда файл исходного кода был прочитайте, прежде чем он был скомпилирован или тест был выполнен.


Относительно root пути к классам

Этими записями управляет проект Lein. в projects.clj:

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

Если у вас нет битов clj и java (некоторые проекты также сегментируют файлы cljc и cljs в отдельные деревья каталогов), вам нужно будет изменить либо project.clj, либо местоположение файла.

0 голосов
/ 26 апреля 2020

На самом деле здесь есть две проблемы:

1) ваша функция foo возвращает nil, и кажется, что функция чтения не может возвращать литеральный ноль. Таким образом, вам действительно нужно вернуть что-то из 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 возвращает 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")

, вероятно, должно работать

...