我在clojure中使用java类,它为包含一系列记录的特定于域的二进制文件提供检索API.
java类用文件初始化,然后提供一个.query方法,该方法返回一个只有一个方法的内部类的实例.next,因此不能很好地使用通常的java集合API.外部类和内部类都不实现任何接口.
该.query方法可以返回null而不是内部类.该.next方法返回一个记录字符串,如果没有找到其他记录,则返回null,它可能在第一次调用时立即返回null.
如何在不编写更多java类的情况下使这个java API在clojure中运行良好?
我能想到的最好的是:
(defn get-records
[file query-params]
(let [tr (JavaCustomFileReader. file)]
(if-let [inner-iter (.query tr query-params)] ; .query may return null
(loop [it inner-iter
results []]
(if-let [record (.next it)]
(recur it (conj results record))
results))
[])))
Run Code Online (Sandbox Code Playgroud)
这给了我一个结果向量来处理clojure seq抽象.是否有其他方法可以使用lazy-seq或使用协议从Java API中公开seq?
对于一个类,我需要编写一些JVM代码,我希望使用Clojure.我让它与软件堆栈的底部一起工作,但是我无法让它在位于顶部和底部的GUI层之间工作.我的主要问题是让Java GUI识别我的Clojure文件.我想使用Leiningen,但Java编译解决方案似乎并不能解释这种互操作.这里的答案似乎正是我所需要的.我不明白在哪里放置代码等(仅仅是不够详细).有人有任何提示吗?
我尝试制作一个插件,但它似乎不起作用.我知道我的案例肯定是在问题的边缘,但一个解决方案将使Clojure在教室环境中更容易使用.
谢谢!
更多细节:
我使用编译的Clojure jar并没有太多运气.我需要创建一个(ugh)有状态的Clojure类(即方法不能是静态的).我的类的代码(src/final_project/MyLinkLayer.clj)看起来像
(ns final_project.MyLinkLayer
(:gen-class))
(defn -init[s] (print s))
(defn -send [dest data len] (println data))
(defn -recv [trans] (println trans))
(defn -status [] (println "I am a status!"))
(defn -command [cmd value] (println (str cmd " with value=" value)))
Run Code Online (Sandbox Code Playgroud)
我的project.clj是
(defproject final_project "0.1.0-SNAPSHOT"
:description "A simulated MAC layer."
:dependencies [[org.clojure/clojure "1.4.0"]
[local/classFiles "1"]]
:aot [final_project.MyLinkLayer])
Run Code Online (Sandbox Code Playgroud)
该类编译("lein compile")很好地编译成"target/classes/final_project /",但方法没有显示出来.我可以通过jar加载类(在我的项目的顶级Java部分使用Maven导入的包工作得很好).我甚至用Eclipse检查了.class文件,生成的唯一方法是来自Object的方法.有什么想法吗?此外,一旦我真正进入我的Clojure课程的"有状态"部分,有没有人有任何想法?提前致谢.
我们正在开发一个有一些Clojure-Java互操作的项目.在这一点上,我们有一个具有各种依赖关系的类,我们将它们放入Eclipse中的用户库进行开发,但当然使用Leiningen(2.x)时没有任何帮助.我们的大多数依赖项都是专有的,因此它们不在某个存储库中.
这样做最简单/最直接的方法是什么?
我见过leiningen - 如何为本地jar添加依赖项?,但它似乎已过时了?
更新:所以我按照这些说明和github上的lein部署文档为我的jar创建了一个本地maven存储库,并编辑了我的project.clj文件,如下所示:
:dependencies [[...]
[usc "0.1.0"]]
:repositories {"usc" "file://maven_repository"}
Run Code Online (Sandbox Code Playgroud)
maven_repository位于项目目录下(因此不使用file:///).当我跑"lein deps"时 - 我收到了这条消息:
Retrieving usc/usc/0.1.0/usc-0.1.0.pom from usc
Could not transfer artifact usc:usc:pom:0.1.0 from/to usc (file://maven_repository): no supported algorithms found
This could be due to a typo in :dependencies or network issues.
Could not resolve dependencies
Run Code Online (Sandbox Code Playgroud)
什么是"找不到支持的算法",我该如何解决?
Update2:在这里找到答案的最后一点.
许多JavaFx方法采用var args,例如Group,它在Java中声明为:
public Group(Node... children)
Run Code Online (Sandbox Code Playgroud)
其他例如:
public KeyFrame(Duration time, KeyValue... values)
Run Code Online (Sandbox Code Playgroud)
我已经发现了...我应该将java数组传递给方法的方法,所以我一直在做这样的事情,
(-> timeline .getKeyFrames
(.addAll
(into-array [(KeyFrame. blabla) (KeyFrame. blabla)]))`
Run Code Online (Sandbox Code Playgroud)
(into-array...)每次有一个var arg时都要这么做很烦人,当var arg是我实际传入的基类时,它会更烦人.例如
(Group. (into-array [(Circle. 100) (Rectangle. 100 100)]))
Run Code Online (Sandbox Code Playgroud)
导致类型不匹配错误.相反,我必须这样做:
(Group. (into-array Node [(Circle. 100) (Rectangle. 100 100)]))
Run Code Online (Sandbox Code Playgroud)
所以我做了这个功能:
(defn make-group [& items]
(Group. (into-array Node items)))
Run Code Online (Sandbox Code Playgroud)
哪个适用于群组,但不能解决一般问题.
那么有没有一种解决省略号/变量问题的好方法,所以我不必为每个vararg方法创建特殊函数?这个函数的要求是它需要你想要调用的方法(例如Group),固定的args,var args,以及某种神奇的函数知道如何找到var args中元素的公共基类.
谢谢
java clojure variadic-functions clojure-java-interop javafx-2
我正在尝试使用以下方法解析一个相当小的(<100MB)xml文件:
(require '[clojure.data.xml :as xml]
'[clojure.java.io :as io])
(xml/parse (io/reader "data/small-sample.xml"))
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
OutOfMemoryError Java heap space
clojure.lang.Numbers.byte_array (Numbers.java:1216)
clojure.tools.nrepl.bencode/read-bytes (bencode.clj:101)
clojure.tools.nrepl.bencode/read-netstring* (bencode.clj:153)
clojure.tools.nrepl.bencode/read-token (bencode.clj:244)
clojure.tools.nrepl.bencode/read-bencode (bencode.clj:254)
clojure.tools.nrepl.bencode/token-seq/fn--3178 (bencode.clj:295)
clojure.core/repeatedly/fn--4705 (core.clj:4642)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/take-while/fn--4236 (core.clj:2564)
Run Code Online (Sandbox Code Playgroud)
这是我的project.clj:
(defproject dats "0.1.0-SNAPSHOT"
...
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/data.xml "0.0.7"]
[criterium "0.4.1"]]
:jvm-opts ["-Xmx1g"])
Run Code Online (Sandbox Code Playgroud)
我尝试在.bash_profile中设置LEIN_JVM_OPTS和JVM_OPTS失败。
当我尝试以下project.clj时:
(defproject barber "0.1.0-SNAPSHOT"
...
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/data.xml "0.0.7"]
[criterium "0.4.1"]]
:jvm-opts ["-Xms128m"])
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Error occurred during initialization of VM
Incompatible minimum and maximum …Run Code Online (Sandbox Code Playgroud) 我正在尝试在Clojure中实现以下Java接口:
package quickfix;
public interface MessageFactory {
Message create(String beginString, String msgType);
Group create(String beginString, String msgType, int correspondingFieldID);
}
Run Code Online (Sandbox Code Playgroud)
以下Clojure代码是我尝试这样做的:
(defn -create-message-factory
[]
(reify quickfix.MessageFactory
(create [beginString msgType]
nil)
(create [beginString msgType correspondingFieldID]
nil)))
Run Code Online (Sandbox Code Playgroud)
这无法编译错误:
java.lang.IllegalArgumentException:无法在接口中定义方法:create
该文档提出重载接口方法都行,只要该元数是不同的,因为它是在这种情况下:
如果方法在协议/接口中过载,则必须提供多个独立的方法定义.如果在接口中重载了相同的arity,则必须指定完全提示以消除歧义 - 缺少提示意味着Object.
我怎样才能使这个工作?
问题基本上说明了一切。
在gen-class中声明函数签名时,对于二维字符串数组,我应该放置什么类型?
[myFunc [XXXX] ReturnType]
Run Code Online (Sandbox Code Playgroud)
我要为XXXX做什么?
更新:按照@Mark Topolnik的建议,我正在尝试
#^{:static true} [myFunc [ ^"[[Ljava.lang.String;" ] clojure.lang.IFn]
Run Code Online (Sandbox Code Playgroud)
在我的声明中,我回来了
java.lang.RuntimeException: Unmatched delimiter: ]
Run Code Online (Sandbox Code Playgroud)
当我尝试编译运行时异常时。
更新2:通过删除上一行中的^进行修复。(这是在gen-class中声明函数签名的上下文中,因此^可能不必要。)
我正在尝试实现遗留运行时所需的Java接口,我正在使用并实例化此实现的实例以将其传递给运行时。但是,当我运行时,lein uberjar我看到一个异常,即找不到该类。这两个名称空间是在同一个leiningen项目中定义的,因此,我希望它们能够彼此看到以及它们生成的类。
(ns man.core
(:require (man.gateway))
(:import (man ManGate)
(eu.m2machine.gw GatewayComponentFactory))
(:gen-class))
(defn -main [& args]
(let [starter (.starter (GatewayComponentFactory/get))
gateway (ManGate.)]
(.startup starter gateway)))
Run Code Online (Sandbox Code Playgroud)
此代码尝试使用在同一项目中实现的类:
(ns man.gateway
(:import [eu.m2machine.gw.text GatewayIDFormatter])
(:gen-class
:name man.ManGate
:implements [eu.m2machine.gw.Gateway]
:prefix "gateway-"))
(defn gateway-startup [this])
(defn gateway-shutdown [this])
Run Code Online (Sandbox Code Playgroud)
到目前为止,接口所需的两种方法仅具有存根实现。他们可以在我编译代码后得到他们的代码。定义了接口(在添加为依赖项的工件中):
package eu.m2machine.gw;
public interface Gateway {
void startup();
void shutdown();
}
Run Code Online (Sandbox Code Playgroud)
我得到的异常是:
Exception in thread "main" java.lang.ClassNotFoundException: man.ManGate, compiling:(man/core.clj:1:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.RT.loadResourceScript(RT.java:372)
at clojure.lang.RT.loadResourceScript(RT.java:363)
at clojure.lang.RT.load(RT.java:453)
at clojure.lang.RT.load(RT.java:419)
at clojure.core$load$fn__5677.invoke(core.clj:5893)
at clojure.core$load.invokeStatic(core.clj:5892) …Run Code Online (Sandbox Code Playgroud) 如何合并两个 hashmap 变量,例如map1和map2?
我试过了(merge map1 map2),但出现以下异常:
ClassCastException java.util.HashMap 不能转换为 clojure.lang.IPersistentCollection
假设我有以下代码:
(def m1 (java.util.HashMap.))
(def m2 (java.util.LinkedHashMap.))
(def m3 {})
Run Code Online (Sandbox Code Playgroud)
我需要一个能够检测来自java的地图的函数,例如:
(map java-map? [m1 m2 m3]) ;; => (true true false)
Run Code Online (Sandbox Code Playgroud)
什么开箱即用?
clojure ×10
java ×3
leiningen ×3
dictionary ×1
interop ×1
iteration ×1
javafx-2 ×1
seq ×1
xml-parsing ×1