簡體   English   中英

使用隱式參數為部分函數定義新的TYPE

[英]Defining new TYPE for partial function with an implicit parameters

我正在嘗試創建一個具有部分函數模式的新TYPE。 例:

新類型

type RouteFunc = (String, HttpServletRequest, HttpServletResponse) => Unit

用法

def myFunc(str:字符串,請求:HttpServletRequest,響應HttpServletResponse)myFunc(“”,Any,Any)

對於顯式傳遞的參數,這確實很好用,但是我想更改此類型定義,以便將HttpServletRequest, HttpServletResponse隱式與顯式傳遞。

預期結果

def myFunc(str: String)(implicit request: HttpServletRequest, response HttpServletResponse)

我找不到一種方法來更改TYPE結構/定義以適應預期的模式,這是可能的還是語言的限制?

編輯

用法:

object Routes{
    type RouteFunc = (String, HttpServletRequest, HttpServletResponse) => Unit

    val routes = Map[String, RouteFunc](
        "/data" -> DataSets.dashboard
    )

    def evaluateRoute()(implicit request: HttpServletRequest, response: HttpServletResponse) = {
        val path = request.getPathInfo

        val route = routes(path)
        route(path, request, response)
    }
}
object DataSets{
    def dashboard(path: String, request: HttpServletRequest, response: HttpServletResponse) = {
        response.setContentType("text/html")
        response.setCharacterEncoding("UTF-8")

        response.getWriter.write("Hello World")
    }
}

我希望def dashboard看起來像:

def dashboard(path: String)(implicit request: HttpServletRequest, response: HttpServletResponse)

編輯2

最后,我明確地傳遞了參數,因為對於@SergGr和@slouc所解釋的當前版本的Scala,這是不可能的:

import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import controllers.data._
import Routes._

class RoutingController() extends JettyHttpServlet {

    type RouteFunc = (String, HttpServletRequest, HttpServletResponse) => Unit
    type HttpRequest = String
    type Path = String

    val routes = Map[(String, HttpRequest), RouteFunc](
        (GET,       "/data")                -> Data.dashboard,
        (GET,       "/assets/*")            -> Assets.getAsset

    )

    override def Get()(implicit request: HttpServletRequest, response: HttpServletResponse): Unit = {
        val path = request.getPathInfo
        val pathTerms = path.split("/")
        val getPaths = routes.filter(_._1._1 == request.getMethod.toUpperCase)

        val filteredList = getPaths.flatMap{
            route =>
                if(route._1._2 == path){
                    Option(route)
                }else {
                    val s = route._1._2.split("/")

                    if(route._1._2.startsWith("/assets")){
                        Option(route)
                    }else
                        None
                }
        }.toSeq

        filteredList.head._2(path, request, response)
    }

}

----------------------

import jetty.Routes
import jetty.Responses._

object Data {

    import javax.servlet.http.{HttpServletRequest, HttpServletResponse}

    def dashboard(path: String, eq: HttpServletRequest, qw: HttpServletResponse): Unit = {
            implicit val s = eq
            implicit val r = qw
        Ok(Routes.html, views.html.data.dashboard.render("Dashboard").toString())
    }

}

如果我的問題正確無誤,您想使用隱式參數定義一個函數。 這是不可能的。 它不僅是一種語言約束,而且還是一種邏輯約束。 函數是一個數學概念,那里沒有所謂的“隱式參數”。 無法提供參數的子集,而其余部分則“從作用域”中獲取。

在Scala中,有一種方法可以將方法轉換為函數。 有問題的機制稱為eta擴展。 給定一些方法fooMethod,則可以將對應的函數fooFunction定義為

def fooMethod(i: Input): Output
val fooFunction: Input => Output = (i: Input) => fooMethod(i)

// or

def fooMethod(i1: Input1, i2: Input2): Output
val fooFunction: Input1 => Input2 => Output = (i1: Input1) => (i: Input2) => fooMethod(i1, i2)

// or

def fooMethod(): Output
val fooFunction: Unit => Output = () => fooMethod()

如果您提供了需要函數的方法,則編譯器將自動執行eta擴展。 如果無法自動執行,則可以手動執行:

val fooFunction = fooMethod _

但是,由於前面提到的原因,如果您引入隱式參數,即使該技巧也失敗了。

例:

trait HttpServletRequest
trait HttpServletResponse

type RouteFunc = String => (HttpServletRequest, HttpServletResponse) => Unit

implicit val request = new HttpServletRequest {}
implicit val response = new HttpServletResponse {}

def myMethod1(str: String)(request: HttpServletRequest, response: HttpServletResponse) = println("1")
def myMethod2(str: String)(implicit request: HttpServletRequest, response: HttpServletResponse) = println("2")

val myFunc1: RouteFunc = myMethod1 _ // compiles fine
val myFunc2: RouteFunc = myMethod2 _ // nope

編輯:

鑒於您的編輯,這就是我的做法:

trait HttpServletRequest
trait HttpServletResponse

object Routes {

  implicit val request = new HttpServletRequest {}
  implicit val response = new HttpServletResponse {}

  type RouteFunc = String => Unit
  val routes = Map[String, RouteFunc]("/data" -> DataSets.dashboard())
}

object DataSets {

  def dashboard()(implicit request: HttpServletRequest, response: HttpServletResponse): RouteFunc =
    (path: String) => {
      // impl of dashboard, uses request and response
  }
}

您將路由定義為功能String => Unit ,並將儀表板定義為采用隱式請求和響應並為您構造路由的方法。

編輯2:

似乎在將來的Scala版本之一中將提供對帶有隱式參數的函數的支持。 我不喜歡這樣,我不會使用它,即使沒有它,我們在Scala中也會有太多隱含的地獄,但是很高興知道這一點,這樣我就不會一直聲稱這是不可能的:)

從Scala 2.12開始不支持隱式函數。 看起來當Dotty成為Scala的官方編譯器時,他們計划將其用於更高版本中的一個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM