如何将参数传递给Clojure中的静态方法?

时间:2018-01-21 13:03:46

标签: java clojure rapidoid

我有以下方法:

package com.streambright.http.handlers;

import org.rapidoid.http.Req;
import org.rapidoid.u.U;

import java.util.Map;

public class EchoHandler {

    public static Map<String, String> handleEcho(Req req) {
        return U.map(req.headers());
    }
}

当我使用它时,它非常好:

On.get("/echo").managed(false).json(EchoHandler::handleEcho);

然而,当我尝试在Clojure中做同样的事情时,它失败的参数数量错误。

处理程序:

(ns s.echo-http-handler
  (:import
    [org.rapidoid.http  Req ]
    [org.rapidoid.u     U   ] )
  (:gen-class
    :methods [^:static [handler [org.rapidoid.http.Req] java.util.Map]]))

(defn -handler
  [Req req]
  (U/map (.headers req)))

当我启动服务器时:

(ns s.http
  (:require
    [s.echo-http-handler  :as echo    ] )
  (:import
    [org.rapidoid.config  Conf  ]
    [org.rapidoid.setup   On    ] ) )

    (defn start
      []
      (set-http-params!)
      (.json (.managed (On/get "/echo") false) echo/-handler))

它启动并抛出以下错误:

clojure.lang.ArityException: Wrong number of args (0) passed to: echo-http-handler/-handler

如何将req传递给Clojure中的函数?

2 个答案:

答案 0 :(得分:3)

我过去经常使用fastoid。你在这里的错误是你试图只传递一个Clojure函数作为处理程序。相反,它应该是ReqHandler Java类的实例。因此,您需要创建一个扩展它的匿名类实例。

错:

(defn -handler
  [Req req]
  (U/map (.headers req)))

正确:

(reify ReqHandler
 (execute [this, ^Req req]
   ;; here, access req's fields to write the body or headers
   ))

答案 1 :(得分:1)

假设问题在于如何处理Clojure功能,以下情况应该有效:

(ns your-namespace
  (:import [org.rapidoid.http Req ReqHandler]))

; Helper to create an object that implements ReqHandler
(defn makeReqHandler [f]
  ; Basically "new ReqHandler {...}"
  (reify ReqHandler
    (execute [this, ^Req req] (f req))

此函数采用Clojure函数,并使用它来创建实现ReqHandler的对象。我认为问题在于(由于某种原因)你想要.json的0-arity重载,当你真的想要将参数传递给回调的重载时。这个助手应该防止这种混乱。

然后用作:

(let [handler (makeReqHandler echo/-handler)]
  (.json (.managed (On/get "/echo") false) handler)))

虽然这也可以写成:

(->  (On/get "/echo")
     (.managed false)
     (.json handler))

或者甚至使用内联处理程序来表明仍然可以使用包装函数来使用简洁的匿名函数语法:

(->  (On/get "/echo")
     (.managed false)
     (.json (makeReqHandler #(U/map (.headers %)))))

可以说更具可读性。因为this在使用Java互操作时总是隐式地是第一个参数,doto->非常适合摆脱嵌套。