我偶尔会遇到以下模式,我基本上有一个PartialFunction[SomeType,AnotherType],并希望将其视为一个Function[SomeType,Option[AnotherType],例如:
def f(s:SomeType):Option[AnotherType] = s match {
case s1:SubType1 => Some(AnotherType(s1.whatever))
case s2:SubType2 => Some(AnotherType(s2.whatever))
case _ => None
}
Run Code Online (Sandbox Code Playgroud)
有没有办法以避免默认情况并将结果包装在Some定义位置的方式编写上述函数?到目前为止我提出的最好的是:
def f(s:SomeType):Option[AnotherType] = pf.lift(s)
def pf:PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在没有定义中间函数的情况下做到这一点?我已经尝试了以下几行,但还没有任何东西可以编译:
def f:Function[SomeType,Option[AnotherType]] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}.lift
Run Code Online (Sandbox Code Playgroud) 如果我做:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { t => t._1 + t._2 }
Run Code Online (Sandbox Code Playgroud)
没关系.
如果我做:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { case (b, n) => b + n }
Run Code Online (Sandbox Code Playgroud)
也没关系.
但如果我这样做:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { (b, n) => b + n }
Run Code Online (Sandbox Code Playgroud)
不起作用.
为什么我应该使用"case"关键字来使用命名元组?
在scala中部分函数的这个解释中,case语句使用如下:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
Run Code Online (Sandbox Code Playgroud)
然后它说:
虽然此代码未显式实现isDefinedAt方法,但它与前面的除法函数定义完全相同
前面的除法函数显式定义了apply和isDefined方法,如下所示:
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
Run Code Online (Sandbox Code Playgroud)
我看到编译器在这里做了一些魔术,但我对机制的本质很好奇:在后台的isDefined体中提取的情况下是守护(如果d!= 0)?多个案例陈述与他们自己的警卫怎么样?函数的域在case语句中定义,因此必须是编译器如何在后台构建isDefined的实现.
我对吗?
在为Actor编写Specs2规范时,我MatchError对一些部分函数的组合感到有点困惑.
一个最小的例子:
val testPf1 = PartialFunction[Any, Boolean]{ case 2 ? true }
val testPf2 = PartialFunction[Any, Boolean]{ case 1 ? true }
val testPf = testPf1 orElse testPf2
testPf.isDefinedAt(1)
testPf.isDefinedAt(2)
testPf(1)
testPf(2)
Run Code Online (Sandbox Code Playgroud)
导致输出:
testPf1: PartialFunction[Any,Boolean] = <function1>
testPf2: PartialFunction[Any,Boolean] = <function1>
testPf: PartialFunction[Any,Boolean] = <function1>
res0: Boolean = true
res1: Boolean = true
scala.MatchError: 1 (of class java.lang.Integer)
at com.dasgip.controller.common.informationmodel.programming.parametersequence.A$A161$A$A161$$anonfun$testPf1$1.apply(PFTest.sc0.tmp:33)
at com.dasgip.controller.common.informationmodel.programming.parametersequence.A$A161$A$A161$$anonfun$testPf1$1.apply(PFTest.sc0.tmp:33)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PFTest.sc0.tmp:243)
at scala.PartialFunction$OrElse.apply(PFTest.sc0.tmp:163)
at #worksheet#.#worksheet#(PFTest.sc0.tmp:36)
Run Code Online (Sandbox Code Playgroud)
那让我很困惑.如果对于给定输入isDefinedAt的两个部分函数的组合返回true,我希望我也可以将apply它输出到同一个.
考虑到以下场景
val items = List("a", "b", "c", 1, 2, 3, false, true)
def intItems = items.collect {case i : Int => i}
def stringItems = items.collect {case s : String => s}
Run Code Online (Sandbox Code Playgroud)
有没有办法创建一个通用函数来处理这种行为?
我尝试了以下方法
def itemsAs[T]: List[T] = items.collect { case item: T => item }
Run Code Online (Sandbox Code Playgroud)
但
itemsAs[Int]
Run Code Online (Sandbox Code Playgroud)
回报
List[Int]] = List(a, b, c, 1, 2, 3, false, true)
Run Code Online (Sandbox Code Playgroud)
另一种方法是提供partial functionas 参数,但仍然必须复制case i: Int => iand case s: String => s。有没有办法让它变得更紧凑?谢谢
在Scala中,"部分功能"的概念与F#的function关键字允许我实现的功能非常相似.然而,Scala的部分函数也允许通过orElse如下所示的方法进行合成:
def intMatcher: PartialFunction[Any,String] = {
case _ : Int => "Int"
}
def stringMatcher: PartialFunction[Any,String] = {
case _: String => "String"
}
def defaultMatcher: PartialFunction[Any,String] = {
case _ => "other"
}
val msgHandler =
intMatcher
.orElse(stringMatcher)
.orElse(defaultMatcher)
msgHandler(5) // yields res0: String = "Int"
Run Code Online (Sandbox Code Playgroud)
我需要知道是否有办法在F#中实现相同的组合功能.
Apologies if this is obvious but I am new to scala and I am getting two unexpected behaviors with the following code:
Seq(1, "a", 2, "b") map {
case i: Int => i+1
}
Run Code Online (Sandbox Code Playgroud)
1) I would have expected to get back a collection where the strings are unchanged and the numbers are incremented by 1 but instead I get an error.
2) I believe the case i: Int => i + 1 syntax represents a partial function which is …
我有一个PartialFuncton[Throwable,Future[Result]]名为errorMap的函数,用于将throwable转换为结果或将来失败.我可以通过做lift和getOrElse这样的:
val x: Future[Result] = errorMap.lift(e).getOrElse(Future.failed(e))
Run Code Online (Sandbox Code Playgroud)
我认为同样应该可以实现applyOrElse,但我似乎无法弄清楚如何调用它来实现这一目标.我误解了什么applyOrElse是为了什么?
我试图了解函数部分应用程序在 Scala 中的工作原理。
为此,我构建了这个简单的代码:
object Test extends App {
myCustomConcat("General", "Public", "License") foreach print
GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
def myCustomConcat(strings: String*): List[Char] = {
val result = for (s <- strings) yield {
s.charAt(0)
}
result.toList
}
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ) = {
myCustomConcat("General", "Public", "License")
}
}
Run Code Online (Sandbox Code Playgroud)
myCostumConcat函数接受输入一个字符串数组,并返回一个包含每个字符串的第一个字母的列表。
所以,代码
myCustomConcat("General", "Public", "License") foreach print
Run Code Online (Sandbox Code Playgroud)
将在控制台上打印:GPL
现在假设我想编写一个函数来生成 GPL 缩写词,使用(作为输入参数)我之前的函数提取每个字符串的第一个字母:
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ): List[Char] = {
myCustomConcat("General", "Public", "License")
}
Run Code Online (Sandbox Code Playgroud)
使用部分应用程序运行这个新函数: …
我想写两个服务,然后用orElse让两个服务组合在一起,即service_one或service_two。它们都是偏函数。
服务一是:
val usersService = HttpService {
case request @ GET -> Root / "users" / IntVar(userId) =>
Ok("test")
}
Run Code Online (Sandbox Code Playgroud)
服务二是:
val versionService = HttpService{
case req @ GET -> Root / "version" => {
val jsonmap = ("origin" -> req.remoteAddr.getOrElse("unknown ip"))
Ok(compact(render(jsonmap)))
}
}
Run Code Online (Sandbox Code Playgroud)
然后我想把它们结合在一起。
val service = userService orElse versionService //the error happens here.
Run Code Online (Sandbox Code Playgroud)
错误是:
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\ServiceApp.scala:46: value orElse is not a member of org.http4s.HttpService
[error] val service = usersService orElse versionService
[error] ^
[error] one …Run Code Online (Sandbox Code Playgroud)