【问题标题】:How do I set up classes in a Lein project?如何在 Lein 项目中设置课程?
【发布时间】:2013-07-31 16:22:21
【问题描述】:

我跑了lein new app hm,然后在hm/src/hm 编辑core.clj 成为:

(ns hm.core
  (:gen-class)
  (:use [hm.hashmap]))

(defn -main []
  (def j (new hm.hashmap))
  (-add j "foo" "bar")
  (println j))

hashmap.clj 是:

(ns hm.hashmap
  (:gen-class
   :methods [[hashmap [] java.util.HashMap]
             [add [String String]]]))

(defn -hashmap []
  (def h (new java.util.HashMap))
  h)

(defn -add [this key value]
  (. this put key value)
  this)

目标是围绕 HashMap 做一个包装器,这样我就可以理解 Clojure 以及它与 Java 的关系。我对 Clojure 还很陌生。但是,当我编译这个时,我在hashmap.clj 中得到了很多 ClassNotFoundException。我怎样才能做到这一点?

【问题讨论】:

  • 找不到什么类?
  • @JeremyHeiler Exception in thread "main" java.lang.ClassNotFoundException: java.lang., compiling:(hm/hashmap.clj:1:1)
  • 这不是在 Clojure 中做事的正常方式,我会将其与从内联汇编块开始学习 C 进行比较——而 clojure 对象成为 jvm 中的类和方法,根据类工作Clojure 中的方法和方法(除了您要引入 java 类的互操作)是一种罕见且专门的东西。我不会从生成 java 类开始,而是从使用 java 类的 Clojure 函数开始,然后从那里开始构建。
  • @noisesmith 感谢您的建议!我可以从哪里开始?
  • 4clojure.comgithub.com/functional-koans/clojure-koans 是对 clojure 的很好的交互式介绍。 O'Reilly Clojure Programming 一书(Chas Emerick 撰写)和 The Joy of Clojure 也是很好的资源,其中包含有关 Java 互操作的全面信息。您在这里尝试的那种互操作几乎只有在您编写希望能够从中调用 Clojure 代码的 Java 代码时才需要 - 反过来更容易。

标签: java class clojure


【解决方案1】:

注意:这是对您问题的直接回答。我不建议你以这种方式学习 Clojure。


您需要先编译您的类,然后才能运行它们。在您的 project.clj 中将其添加到地图中:

:aot [hm.hashmap]

然后你需要运行lein compile 来编译这些类。您应该看到输出表明 hm.hashmap 类已编译。之后运行lein run 调用hm.core 中的“main”函数。

我删除了您的 gen-class 的 :methods 部分,因为您已经在下面定义了它们,这导致了奇怪的 java.lang., 错误。你会遇到其他错误,但这应该足以让你通过这个问题。

【讨论】:

  • 好吧,我添加了aot 行并编译,但在lein run 中我得到:Exception in thread "main" java.lang.IllegalArgumentException: No matching method found: put for class hm.hashmap。现在我知道这是学习 Clojure 的错误方法,所以你能指出我正确的方向吗?
  • @tekknolagi 就像他说的,“你会遇到其他错误”。有关使此运行几乎保持原样的最短编辑,请参阅我的答案。有关 Clojure 的一般资源,请参阅the Clojure tag info
【解决方案2】:

您的代码还有一些其他问题,但这里最直接的问题是add 的签名不完整。你的add 返回this,一个hm.hashmap

要解决此问题,请将签名更改为返回 Object,或者通过额外编辑返回 java.util.HashMap。如果您希望它以其他方式工作,您还需要扩展而不是封装。

(ns hm.hashmap
  (:gen-class
   :extends java.util.HashMap
   :methods [[add [String String] java.util.HashMap]]))

最后将core.clj中的-main更改为使用.add调用方法,而不是尝试访问私有-add

...
(.add j "foo" "bar")
...

然后

lein clean
lein compile hm.core hm.hashmap
lein run

应该打印

#<hashmap {foo=bar}>

请注意,据我所知,由于符号解析的时间安排,您不能指定在签名中返回 hm.hashmap。见GC Issue 81: compile gen-class fail when class returns self

【讨论】:

  • @tekknolagi 查看编辑,您还需要将core.clj 中的-add 更改为.add 才能使用该方法(而不是尝试访问私有函数)。
  • @tekknolagi 嗯,和:extends java.util.HashMap。有趣的是,我不假思索地立即对原件进行了多少次编辑。请记住,正如其他人所暗示的那样,您会发现更好的方法来完成我最终在 Clojure 中编辑的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
相关资源
最近更新 更多