标签: clojure-java-interop

是否有任何问题包括一个用clojure编写的jar作为Android应用程序的一部分?

我正在开发一个标准的Android应用程序(在java中),但是想在clojure中实现一些非UI"业务逻辑".这样做是否有任何缺点,或者我应该注意哪些问题会使这个想法变得糟糕?

我做了一个简单的测试 - 在Android应用程序的一个简单的clojure库中调用函数,这似乎没有任何明显的问题.

我已经看到关于加载clojure.jar的时间问题的评论,但在我的情况下,clojure没有处理UI.

我不清楚是否还有其他内存或性能问题我应该关注.

2017年1月16日更新

尝试使用一些稍微复杂的clojure库时遇到了一些问题,特别是依赖于core.async的库.

使用标准的clojure 1.8作为依赖,我试图:

new ClassDefinedInClojure()
Run Code Online (Sandbox Code Playgroud)

ClassDefinedInClojure是AOT生成的java类,但我得到了:

java.lang.VerifyError: Rejecting class clojure.core.memoize.RetryingDelay because it failed compile-time verification
Run Code Online (Sandbox Code Playgroud)

我认为这是此处确定的同一问题的结果:

http://dev.clojure.org/jira/browse/CLJ-1472

但是,即使在我使用补丁(http://dev.clojure.org/jira/secure/attachment/15351/clj-1472-2.patch)重建clojure 1.8之后问题仍然存在.

我知道clojure的android特定版本https://github.com/clojure-android/clojure,但老实说不清楚这与正常的clojure有何不同以及为什么需要它.我尝试使用它作为标准clojure库的替代品,但有同样的问题.

关于我原来的问题,这很有用 - http://blog.ndk.io/state-of-coa.html

android clojure clojure-java-interop

7
推荐指数
0
解决办法
154
查看次数

从scala sbt任务调用clojure代码

我试图将一些clojure代码称为sbt任务.

我的build.sbt看起来像,

lazy val aTask = taskKey[Unit]("a task")

libraryDependencies ++= Seq(
"org.clojure" % "clojure" % "1.9.0"
)

import clojure.java.api.Clojure
import clojure.lang.IFn

aTask := {
val plus: IFn = Clojure.`var`("clojure.core", "+")
println(plus.invoke(1, 4))
}
Run Code Online (Sandbox Code Playgroud)

project/build.sbt的内容

resolvers += Resolver.mavenLocal

libraryDependencies ++= Seq(
   "org.clojure" % "clojure" % "1.9.0"
 )
Run Code Online (Sandbox Code Playgroud)

我还在项目的project/build.sbt中添加了clojure dep.

调用任务时出现以下错误

[error] java.lang.ExceptionInInitializerError
[error] at clojure.lang.Namespace.<init>(Namespace.java:34)
[error] at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
[error] at clojure.lang.Var.intern(Var.java:148)
[error] at clojure.java.api.Clojure.var(Clojure.java:82)
[error] at clojure.java.api.Clojure.<clinit>(Clojure.java:96)
[error] at $2d5a9b65ddee7e6a09cc$.$anonfun$$sbtdef$1(build.sbt:20)
[error] at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
[error] at sbt.std.Transform$$anon$3.$anonfun$apply$2(System.scala:46)
[error] at sbt.std.Transform$$anon$4.work(System.scala:66)
[error] at …
Run Code Online (Sandbox Code Playgroud)

scala clojure sbt clojure-java-interop

7
推荐指数
1
解决办法
269
查看次数

如何在 clojure 中添加类型提示以修复“无法解析ctor”反射警告,即调用构造函数?

以下示例函数使用 Clojure 的 Java 互操作的特殊形式来调用类构造函数,会导致反射警告:

(defn test-reflection-err []
  (new java.util.HashMap {}))
Run Code Online (Sandbox Code Playgroud)

该消息内容如下:

Reflection warning, /Users/ethan/Projects/scicloj/tablecloth.time/src/tablecloth/time/index.clj:26:3 - call to java.util.HashMap ctor can't be resolved.
Run Code Online (Sandbox Code Playgroud)

我试过放置类型提示来避免这种情况,但不确定将它们放置在哪里以防止反射错误。有谁知道如何做到这一点?

我试过了:

(defn test-reflection-err []
  (^TreeMap new java.util.HashMap {}))
Run Code Online (Sandbox Code Playgroud)

(defn test-reflection-err []
  (doto ^TreeMap (new java.util.HashMap {})))
Run Code Online (Sandbox Code Playgroud)

clojure clojure-java-interop

7
推荐指数
1
解决办法
134
查看次数

如何使用Clojure的gen-class创建多个Java成员变量

这个答案约Clojure的Java的互操作一个非常古老的问题,介绍了如何使用gen-class:state:init关键字来创建一个单一的公共实例变量从Java访问.如果您只需要一个可用于Java类的数据,或者您可以要求Java类使用读取函数(例如,存储在状态变量中的映射),这就足够了.该方法还允许数据改变,例如通过将atoms 存储在状态变量中.

如果我想创建多个可直接在Java类中读取的实例变量,该怎么办?这可能吗?例如,我可以编译以下文件并执行Bar该类,并查看foo.bar打印出来的值42 .

Foo.clj:

(ns students.Foo
  (:gen-class
    :name students.Foo
    :state bar
    ; :state baz
    :init init))

(defn -init
  []
  [[] 42])
Run Code Online (Sandbox Code Playgroud)

Bar.java:

package students;

public class Bar {

    public static void main(String[] args) {
        Foo foo = new Foo();
        System.out.println(foo.bar);
        // System.out.println(foo.baz);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我取消注释baz行,Bar.java将无法编译 - 编译器似乎随机创建barbaz作为状态变量Foo,因此只有其中一个可用Bar.无论如何,我没有看到如何初始化barbaz使用init函数.

java clojure clojure-java-interop

6
推荐指数
1
解决办法
170
查看次数

单线程上下文中volatile-mutable字段的风险?

在单线程程序中使用:volatile-mutable限定符是否安全deftype?这是一个跟进这个问题,这一个这一个.(这是一个Clojure问题,但我添加了"Java"标签,因为Java程序员也可能对它有洞察力.)

我发现在一个程序中我可以通过使用:volatile-mutable字段deftype而不是原子来获得显着的性能提升,但我很担心,因为文档字符串deftype说:

请注意,可变字段非常难以正确使用,并且只是为了便于在Clojure本身中构建更高级别的构造,例如Clojure的引用类型.它们仅供专家使用 - 如果:volatile-mutable或:unynchronized-mutable的语义和含义对您来说不是很明显,那么您就不应该使用它们.

事实上,语义和影响:volatile-mutable不会马上对我明显.

然而,Emerick,Carper和Grand 的Clojure Programming第6章说:

这里的"Volatile"与Java中的volatile字段修饰符含义相同:读取和写入都是原子的,必须按程序顺序执行; 即,它们不能由JIT编译器或CPU重新排序.因此,挥发性物质并不令人惊讶,并且不会引起线程安全 - 但不协调,仍然完全对种族条件开放.

这似乎暗示只要访问单个volatile-mutable deftype字段都发生在一个线程中,就没有什么特别值得担心的了.(没有什么特别的,因为我还是要小心,我是如何处理的状态,如果我可能会使用懒惰序列.)因此,如果没有引入并行到我的Clojure程序,应该使用没有特殊的危险deftype:volatile-mutable.

那是对的吗?我不明白有什么危险?

java clojure thread-safety clojure-java-interop

6
推荐指数
1
解决办法
322
查看次数

如何使用 Maven 将 Clojure 依赖项包含到 Java 项目中

我对 JVM 的所有东西都很陌生,想要启动一个包含 Clojure 库作为依赖项的 Java 项目。我已经看到了有关如何从 Java 运行 Clojure 代码的问题,但是当我尝试在 后运行 jar 文件时mvn package,我得到cannot find symbolvariable Clojure. 到目前为止我的代码看起来像这样:

package org.example;

import clojure.java.api.Clojure;
import clojure.lang.IFn;

public class App 
{
    public static void main( String[] args )
    {

        IFn plus = Clojure.var("clojure.core", "+");
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的 pom 文件如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>project</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>poi</name>
  <properties>
    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>
  </properties>
  <url>http://maven.apache.org</url>
  <repositories>
    <repository>
      <id>clojars</id>
      <url>https://repo.clojars.org/</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>true</enabled> …
Run Code Online (Sandbox Code Playgroud)

java clojure maven clojure-java-interop

6
推荐指数
1
解决办法
1940
查看次数

如何为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中的类型提示进行泛型类

我试图从一个在clojure中运行的Apache flink中得到一个小例子,但是现在我被卡住了,因为clojure中的类型暗示和flink中的一些奇怪的怪癖.

这是我的代码:

(ns pipeline.core
 (:import
 (org.apache.flink.api.java ExecutionEnvironment)
 (org.apache.flink.api.common.functions FlatMapFunction)
 (org.apache.flink.api.java.tuple Tuple2)
 (org.apache.flink.util Collector)
 (java.lang String)))

(def flink-env (ExecutionEnvironment/createLocalEnvironment))

(def dataset (.fromElements flink-env (to-array ["please test me"])))

(defn tokenizer [] (reify FlatMapFunction
                 ( flatMap [this value collector] 
                   (println value))))

(.flatMap dataset (tokenizer))
Run Code Online (Sandbox Code Playgroud)

如果我不提供类型提示,我从flink api收到错误:

Caused by: java.lang.IllegalArgumentException: The types of the interface org.apache.flink.api.common.functions.FlatMapFunction could not be inferred. Support for synthetic interfaces, lambdas, and generic types is limited at this point.
at org.apache.flink.api.java.typeutils.TypeExtractor.getParameterType(TypeExtractor.java:662)
Run Code Online (Sandbox Code Playgroud)

如果我提供类型提示:

(defn tokenizer [] (reify FlatMapFunction
                 ( ^void …
Run Code Online (Sandbox Code Playgroud)

generics clojure type-hinting clojure-java-interop apache-flink

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

不能在ns:gen-class中使用来自另一个命名空间的类

我有一个defrecord名为ConstraintLookupsre.plan.dsl.constraint命名空间.我想在gen-class放置在sre.plan.compiler命名空间的方法中使用其生成的类:

(ns sre.plan.compiler
  (:require
    [sre.plan.dsl.constraint :as constraint])
  (:import (sre.plan.dsl.constraint ConstraintLookup))
  (:gen-class
    :name sre.plan.Compiler
    :methods [^:static [makeConstraintLookupFromTargetsAndBounds 
                         [Iterable Iterable] ConstraintLookup]]))
Run Code Online (Sandbox Code Playgroud)

我用nebula-clojure插件和Gradle进行AOT编译.编译器遇到ns声明时会发出错误:

> Task :sre:compileClojure
Exception in thread "main" java.lang.ClassNotFoundException: java.lang.ConstraintLookup, compiling:(sre/plan/compiler.clj:1:1)
Run Code Online (Sandbox Code Playgroud)

类似地,当sre.plan.dsl.constraint.Constraint在方法声明中使用完全限定时,我得到:

Exception in thread "main" java.lang.ClassNotFoundException: sre.plan.dsl.constraint.ConstraintLookup, compiling:(sre/plan/compiler.clj:1:1)
Run Code Online (Sandbox Code Playgroud)

这里有什么问题?我搞不清楚了.

更新:

引用的ns看起来像这样:

(ns sre.plan.dsl.constraint
  (:require [clojure.set :refer :all]
            [clojure.algo.generic.functor :refer :all]))

(defrecord ConstraintLookup [free bound])
Run Code Online (Sandbox Code Playgroud)

更新:

在我看来,无论如何,在gen-class中你必须使用完全限定的类名.但是我仍然不明白为什么具有完全限定名称的版本不起作用.

clojure clojure-java-interop

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

提高 Clojure 中点云边界框计算的性能

我正在计算 Clojure 中 3d 点云的边界框。点云表示为 Java 原始浮点数组,点云中的每个点都使用 4 个浮点存储,其中最后一个浮点未使用。像这样:

[x0 y0 z0 u0  x1 y1 z1 u1 .... ]
Run Code Online (Sandbox Code Playgroud)

点云的大小为 19200,即数组中的 4*19200 个浮点数。

其中一些值可能不是有限的(它们是无限的或 NaN)。因此,任何包含非有限值的点都应完全排除在计算之外。我已经在 J​​ava 和 Clojure 中实现了这个计算,但是出于某种原因,Clojure 版本仍然慢了大约 4 到 5 倍。

这是 Clojure 代码的样子:

(defn good-compute-bbox [^floats data]
  (let [n (alength data)]
    (loop [i (int 0)
           minx (float (aget data 0))
           maxx (float (aget data 0))
           miny (float (aget data 1))
           maxy (float (aget data 1))
           minz (float (aget data 2))
           maxz (float (aget data 2))]
      (if …
Run Code Online (Sandbox Code Playgroud)

performance geometry clojure clojure-java-interop

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