标签: clojure-java-interop

来自clojure a与非标准迭代java API的互操作

我在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?

iteration clojure seq clojure-java-interop

5
推荐指数
1
解决办法
294
查看次数

用Leiningen夹在Java之间的Clojure

对于一个类,我需要编写一些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课程的"有状态"部分,有没有人有任何想法?提前致谢.

java interop clojure leiningen clojure-java-interop

5
推荐指数
1
解决办法
618
查看次数

如何为Leiningen配置专有依赖项?

我们正在开发一个有一些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:这里找到答案的最后一点.

clojure leiningen clojure-java-interop

5
推荐指数
1
解决办法
1428
查看次数

Clojure和JavaFX 2 - 将多个arity参数传递给JavaFX方法

许多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

5
推荐指数
1
解决办法
336
查看次数

Clojure Leining REPL OutOfMemoryError Java堆空间

我正在尝试使用以下方法解析一个相当小的(<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 out-of-memory xml-parsing clojure-java-interop

5
推荐指数
1
解决办法
2645
查看次数

Clojure使用重载方法来重新定义Java接口

我正在尝试在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.

我怎样才能使这个工作?

clojure clojure-java-interop

5
推荐指数
1
解决办法
2282
查看次数

我该如何调用Clojure函数,该函数需要Java中的二维字符串数组?

问题基本上说明了一切。

在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 clojure clojure-java-interop

5
推荐指数
1
解决办法
146
查看次数

leiningen:项目“ lein run” /“ lein uberjar”上存在的类的ClassNotFoundException

我正在尝试实现遗留运行时所需的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)

clojure leiningen clojure-java-interop

5
推荐指数
1
解决办法
534
查看次数

如何在 Clojure 上合并两个哈希图?

如何合并两个 hashmap 变量,例如map1map2

我试过了(merge map1 map2),但出现以下异常:

ClassCastException java.util.HashMap 不能转换为 clojure.lang.IPersistentCollection

clojure clojure-java-interop

4
推荐指数
1
解决办法
280
查看次数

如何区分java地图和clojure地图?

假设我有以下代码:

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

什么开箱即用?

dictionary clojure clojure-java-interop

4
推荐指数
1
解决办法
258
查看次数