Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 在clojure中为泛型类提供类型提示_Generics_Clojure_Type Hinting_Clojure Java Interop_Apache Flink - Fatal编程技术网

Generics 在clojure中为泛型类提供类型提示

Generics 在clojure中为泛型类提供类型提示,generics,clojure,type-hinting,clojure-java-interop,apache-flink,Generics,Clojure,Type Hinting,Clojure Java Interop,Apache Flink,我试图从clojure中运行的ApacheFlink中获得一个小示例,但是现在我被卡住了,因为clojure中的类型暗示和flink中的一些奇怪的怪癖 这是我的密码: (ns pipeline.core (:import (org.apache.flink.api.java ExecutionEnvironment) (org.apache.flink.api.common.functions FlatMapFunction) (org.apache.flink.api.java.tup

我试图从clojure中运行的ApacheFlink中获得一个小示例,但是现在我被卡住了,因为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))
如果我不提供类型提示,我会从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)
如果我提供类型提示:

(defn tokenizer [] (reify FlatMapFunction
                 ( ^void flatMap [this ^String value ^Collector collector] 
                   (println value))))
我从clojure编译器中得到一个错误:

Caused by: java.lang.IllegalArgumentException: Can't find matching method: flatMap, leave off hints for auto match.
at clojure.lang.Compiler$NewInstanceMethod.parse(Compiler.java:8065) 
有没有办法在clojure中使用泛型类添加类型提示? 应该是这样的:

(defn tokenizer [] (reify FlatMapFunction
                 ( ^void flatMap [this ^String value ^Collector<Tuple2<String, Integer>> collector] 
                   (println value))))
(defproject pipeline "0.1.0-SNAPSHOT"
 :description "FIXME: write description"
 :url "http://example.com/FIXME"
 :license {:name "Eclipse Public License"
        :url "http://www.eclipse.org/legal/epl-v10.html"}
 :dependencies [[org.clojure/clojure "1.7.0"]               
             [org.apache.flink/flink-java "0.9.0"]              
             ]
  :aot :all)

Clojure无法处理反射,因此需要通过Flink method
returns
手动指定返回类型

(.returns (.flatMap dataset (tokenizer)) String)
此外,您需要使用
deftype
来定义
tokenizer
,并在使用它时实例化一个新对象,因为Flink无法处理匿名类:

(deftype tokenizer [] FlatMapFunction
                      (flatMap [this value collector] 
                        (println value)))

(.flatMap dataset (tokenizer.))
下面是一个完整的“单词计数示例”,它可以打包到一个jar中并执行

注意类型提示和类型转换。对于
tokenizer
输出,需要
(int 1)
,否则
Long
将是第二种类型的
Tuple2
。此外,我们使用一个字符串来声明
标记器的输出类型(类类型是不够的,因为还必须指定反射类型)。最后,我们需要键入hint
(int array[0])
,以解决
groupBy
的重载问题(没有它,该方法对Clojure编译器来说是不明确的)

(ns org.apache.flink.flink-clojure.WordCount
(:进口
(org.apache.flink.api.common.functions FlatMapFunction)
(org.apache.flink.api.java数据集)
(org.apache.flink.api.java ExecutionEnvironment)
(org.apache.flink.api.java.tuple Tuple2)
(org.apache.flink.util收集器)
(java.lang字符串)
(:require[clojure.string:as str])
(:gen类)
(def flink env(ExecutionEnvironment/createLocalEnvironment))
(def text(.frommelements flink env(到数组[“请测试我和我自己”]))
(deftype标记器[]FlatMapFunction
(flatMap[此值收集器]
(doseq[v(str/分割值#“\s”)]
(.collect收集器(Tuple2.v(int 1‘‘‘‘‘)’))
(def标记(.returns(.flatMap text(标记器。))“Tuple2”))
(def计数(.sum(.groupBy令牌(int数组[0]))1))
(defn-main[]
(.打印计数)
)

作为此评论的后续行动

对于最新的flink版本(在1.6.1上测试),您需要定义一个自定义类,否则会出现如下错误:

Exception in thread "main" java.lang.IllegalArgumentException: No matching method found: returns for class org.apache.flink.api.java.operators.FlatMapOperator, compiling:(WordCount.clj:69:13)
自定义类:

package org.apache.flink.java;

import org.apache.flink.api.java.tuple.Tuple2;


public class WordCountTuple extends Tuple2<String, Integer> {

}

这里的工作示例fork

Hi,不幸的是,这没有帮助,我仍然得到“无法推断接口org.apache.flink.api.common.functions.FlatMapFunction的类型”的异常。但是感谢您的输入,我将进一步研究SingleInputUDFOOperator。顺便说一句,它应该是“(.returns(.flatMap-dataset(tokenizer))String”,因此,我直接在java中尝试了同样的方法。我修改了wordcount示例,以便标记器只实现“FlatMapFunction”(没有泛型)。即使使用“.returns”(“Tuple2”)我也会得到同样的异常。因此,也许我需要为我的目的编写一个额外的java包装器来处理泛型类型。嗨,中的错误现在已在当前主程序中修复。我刚刚更新了我的答案(包括完整的字数示例)。对于字符串类型提示@MatthiasJ.Sax,您对如何使用可选的
TypeHint
方法签名来实现这一点有什么想法吗?我想一点也没有……Clojure无法处理Java泛型。您需要定义一个自定义类
MyType extensed Tuple2
,然后使用它(您完全可以省略
返回值
,因为对于自定义的“MyType”,Flink将能够自动确定返回类型。)
package org.apache.flink.java;

import org.apache.flink.api.java.tuple.Tuple2;


public class WordCountTuple extends Tuple2<String, Integer> {

}
(ns org.apache.flink.clojure.WordCount
  (:import
   (org.apache.flink.api.common.functions FlatMapFunction)
   (org.apache.flink.api.java DataSet)
   (org.apache.flink.api.java ExecutionEnvironment)
   (org.apache.flink.api.java.tuple Tuple2)
   (org.apache.flink.java WordCountTuple)
   (org.apache.flink.util Collector)
   (java.lang String))
  (:require [clojure.string :as str])
  (:gen-class))

(def flink-env (ExecutionEnvironment/getExecutionEnvironment))

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

(deftype tokenizer [] FlatMapFunction
         (flatMap [this value collector]
           (doseq [v (str/split value #"\s")]
             (.collect collector (Tuple2. v (int 1))))))

(def tokens (.returns (.flatMap text (tokenizer.)) WordCountTuple))

(def counts (.sum (.groupBy tokens (int-array [0])) 1))

(defn -main []
  (.print counts))