[英]Defining new TYPE for partial function with an implicit parameters
I am trying to create a new TYPE that would have a pattern of a partial function. 我正在尝试创建一个具有部分函数模式的新TYPE。 Example: 例:
New Type : 新类型 :
type RouteFunc = (String, HttpServletRequest, HttpServletResponse) => Unit
Usage : 用法 :
def myFunc(str: String, request: HttpServletRequest, response HttpServletResponse) myFunc("", Any, Any) def myFunc(str:字符串,请求:HttpServletRequest,响应HttpServletResponse)myFunc(“”,Any,Any)
For explicitly passed parameters this works really well but I would like to change this type definition so that HttpServletRequest, HttpServletResponse
would be passed in implicitly vs. explicitly 对于显式传递的参数,这确实很好用,但是我想更改此类型定义,以便将HttpServletRequest, HttpServletResponse
隐式与显式传递。
Expected result : 预期结果 :
def myFunc(str: String)(implicit request: HttpServletRequest, response HttpServletResponse)
I can't find a way how to change the TYPE structure/definition to accomodate the intended pattern, is it possible or is that a language restraint? 我找不到一种方法来更改TYPE结构/定义以适应预期的模式,这是可能的还是语言的限制?
EDIT : 编辑 :
Usage: 用法:
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")
}
}
I want the def dashboard
to look like: 我希望def dashboard
看起来像:
def dashboard(path: String)(implicit request: HttpServletRequest, response: HttpServletResponse)
EDIT 2 : 编辑2 :
At the end I went with passing the parameters explicitly as it's impossible with the current version of Scala as explained by @SergGr and @slouc: 最后,我明确地传递了参数,因为对于@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())
}
}
If I got your question correctly, you want to define a function with implicit parameters. 如果我的问题正确无误,您想使用隐式参数定义一个函数。 This is not possible. 这是不可能的。 Not only is it a language constraint, it's also a logical one. 它不仅是一种语言约束,而且还是一种逻辑约束。 Functions are a mathematical concept and there's no such thing as "implicit parameters" there. 函数是一个数学概念,那里没有所谓的“隐式参数”。 There's no way to provide a subset of parameters, and take the rest "from the scope". 无法提供参数的子集,而其余部分则“从作用域”中获取。
In Scala there's a way to transform a method into a function; 在Scala中,有一种方法可以将方法转换为函数。 the mechanism in question is called eta-expansion. 有问题的机制称为eta扩展。 Given some method fooMethod, then a corresponding function fooFunction can be defined as 给定一些方法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()
Compiler will perform eta-expansion automatically if you provide a method where a function is expected. 如果您提供了需要函数的方法,则编译器将自动执行eta扩展。 In cases where it doesn't do it automatically, you can do it manually: 如果无法自动执行,则可以手动执行:
val fooFunction = fooMethod _
But even that trick fails if you introduce implicit parameters, for reasons stated earlier. 但是,由于前面提到的原因,如果您引入隐式参数,即使该技巧也失败了。
Example: 例:
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
EDIT: 编辑:
Given your edit, this is how I would do it: 鉴于您的编辑,这就是我的做法:
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
}
}
You define a route as a function String => Unit
, and you define the dashboard as a method which takes implicit request and response and constructs a route for you. 您将路由定义为功能String => Unit
,并将仪表板定义为采用隐式请求和响应并为您构造路由的方法。
EDIT2: 编辑2:
Looks like support for functions with implicit parameters is coming in one of the future Scala versions. 似乎在将来的Scala版本之一中将提供对带有隐式参数的函数的支持。 I don't like this and I won't use it, we have too much implicit hell in Scala even without it, but it's good to know about it so that I don't keep claiming it's impossible :) 我不喜欢这样,我不会使用它,即使没有它,我们在Scala中也会有太多隐含的地狱,但是很高兴知道这一点,这样我就不会一直声称这是不可能的:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.