我想把一个Try[Option[T]]变成一个Try[T]
这是我的代码
def flattenTry[T](t: Try[Option[T]]) : Try[T] = {
t match {
case f : Failure[T] => f.asInstanceOf[Failure[T]]
case Success(e) =>
e match {
case None => Failure[T](new Exception("Parsing error"))
case Some(s) => Success(s)
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的办法 ?
什么是更惯用的处理方式Option,map/ getOrElse或match?
val x = option map {
value => Math.cos(value) + Math.sin(value)
} getOrElse {
.5
}
Run Code Online (Sandbox Code Playgroud)
要么
val x = option match {
case Some(value) => Math.cos(value) + Math.sin(value)
case None => .5
}
Run Code Online (Sandbox Code Playgroud) 在内部构建集合时Option,每次尝试使集合的下一个成员都可能失败,从而使集合整体失败.在第一次未能成为会员时,我想立即放弃并返回None整个收藏.在Scala中执行此操作的惯用方法是什么?
这是我提出的一种方法:
def findPartByName(name: String): Option[Part] = . . .
def allParts(names: Seq[String]): Option[Seq[Part]] =
names.foldLeft(Some(Seq.empty): Option[Seq[Part]]) {
(result, name) => result match {
case Some(parts) =>
findPartByName(name) flatMap { part => Some(parts :+ part) }
case None => None
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,如果任何调用findPartByName返回None,则allParts返回None.否则,allParts返回Some包含集合的集合Parts,所有集合都保证有效.空集合是可以的.
以上优点是它findPartByName在第一次失败后停止呼叫.但foldLeft无论如何,仍然会为每个名称迭代一次.
这是一个版本,只要findPartByName返回一个拯救None:
def allParts2(names: Seq[String]): Option[Seq[Part]] = Some(
for (name <- …Run Code Online (Sandbox Code Playgroud) 我正在编写Java代码生成器.
我有一个不可变的Map,它包含从java.sql.Types[Int]到(String, String)第一个值为Java类型的元组的映射,第二个是Java包,如果默认情况下未导入该类型,则从该包导入该类型(java.lang):
val SqlTypesToJavaTypeNames =
Map(Types.BIGINT -> ("Long", None),
Types.BINARY -> ("byte[]", None),
Types.BIT -> ("Boolean", None),
Types.BOOLEAN -> ("Boolean", None),
Types.CHAR -> ("String", None),
Types.DATE -> ("Date", Some("java.sql.Date")),
Types.DECIMAL -> ("BigDecimal", Some("java.math.BigDecimal")),
Types.DOUBLE -> ("Double", None),
Types.FLOAT -> ("Float", None),
Types.INTEGER -> ("Integer", None),
Types.LONGNVARCHAR -> ("String", None),
Types.LONGVARCHAR -> ("String", None),
Types.NCHAR -> ("String", None),
Types.NUMERIC -> ("BigDecimal", None),
Types.NVARCHAR -> ("String", None),
Types.REAL -> ("Float", None),
Types.SMALLINT -> ("Short", None), …Run Code Online (Sandbox Code Playgroud) 我已经读过scala中的if语句总是返回一个表达式
所以我正在尝试执行以下操作(伪代码)
sql = "select * from xx" + iif(order.isDefined, "order by " order.get, "")
Run Code Online (Sandbox Code Playgroud)
我正在尝试
val sql: String = "select * from xx" + if (order.isDefined) {" order by " + order.get} else {""}
Run Code Online (Sandbox Code Playgroud)
但我得到这个错误:
illegal start of simple expression
Run Code Online (Sandbox Code Playgroud)
订单是一个选项[String]
我只想要一个方法的可选参数,如果没有传递那个参数(在这种情况下是顺序),那么就跳过它
什么是最惯用的方式来实现我想要做的事情?
- 编辑 -
我想我匆匆忙忙问道
我发现这样,
val orderBy = order.map( " order by " + _ ).getOrElse("")
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
我以为地图是出于其他目的......
我确信这是有充分理由的,但我没有看到它.
Fold在(比如)List返回
op在所有元素之间应用折叠运算符的结果z
它有明显的关系foldLeft并且foldRight做同样的事情,但是定义了顺序(所以不需要关联运算符)
Fold在Option回报
如果非空,则返回应用于
f此scala.Option值的结果scala.Option.否则,计算表达式ifEmpty.
ifEmpty列表的(在位置)z. f是(在的位置)op
对于None(使用我的心理模型Option作为"容器",可能包含或不包含值,是一个"空"容器),事情都可以,Option.fold返回零(值ifEmpty).
对于Some(x),不过,不应该f采取两个参数,z并x因此它与一致fold的序列(包括具有类似的关系foldLeft和foldRight).
肯定存在一个针对此的实用程序论点 - 在实践中f仅x作为参数可能更方便.在大多数情况下,如果确实如此z,那将被忽略.但一致性也很重要......
那么有人可以向我解释为什么foldOption仍然是"合适的" fold吗?
当我有一个Option[T]实例时,很容易T使用map()和等的monadic操作执行任何操作flatMap().这样我就不必进行检查以确定它是定义的还是空的,并且链操作一起最终得到一个Option[R]结果R.
我的困难在于是否有类似的优雅方式在两个Option[T]实例上执行功能.
让我们举一个简单的例子,我有两个瓦尔斯x和y类型Option[Int].如果它们都被定义,我想获得它们的最大值,或者如果只定义了一个,那么我想得到它们的最大值,None如果没有定义的话.
如果没有在第一个isDefined内部进行大量检查,那么如何优雅地写出这个?map()Option
我写了一种方法,可以通过执行api调用来丰富个人数据并添加丰富的数据。
所以我有这个案例类:
case class Person(personData: PersonData, dataEnrichment: Option[DataEnrichment])
Run Code Online (Sandbox Code Playgroud)
我的方法假设要返回此case类。
但我之前没有几个过滤器
如果人身高不是,"1.8 m"或者如果使用正则表达式未在生物中找到personId,我想返回PersondataEnrichment = None
我的问题是,人身高和personId本身就是选项。
所以看起来像这样:
def enrichPersonObjWithApiCall(person: Person) = {
person.personData.height.map(_.equals("1.8 m")) match {
case Some(true) =>
val personId = person.personData.bio flatMap { comment =>
extractPersonIdIfExists(comment)
}
personId match {
case Some(perId) =>
apiCall(perId) map { apiRes =>
Person(
person.personData,
dataEnrichment = apiRes)
}
case _ =>
Future successful Person(
person.personData,
dataEnrichment = None)
}
case _ =>
Future successful Person(
person.personData,
dataEnrichment = None) …Run Code Online (Sandbox Code Playgroud) 我使用 upickle 在 scalajs 中序列化 json。我需要能够解析由空值和缺失字段(网络上的标准 json)表示的可选字段。
使用 OptionPickler,我可以接受可为空的项目。但是,我如何接受缺少的字段?下面的这个例子处理空name字段,但它在缺少的address字段上失败。
// from http://www.lihaoyi.com/upickle/ -> object OptionPickler
object OptionPickler extends upickle.AttributeTagged {
override implicit def OptionWriter[T: Writer]: Writer[Option[T]] =
implicitly[Writer[T]].comap[Option[T]] {
case None => null.asInstanceOf[T]
case Some(x) => x
}
override implicit def OptionReader[T: Reader]: Reader[Option[T]] = {
new Reader.Delegate[Any, Option[T]](implicitly[Reader[T]].map(Some(_))) {
override def visitNull(index: Int) = None
}
}
}
case class Person(id: Int, name: Option[String], address: Option[String])
implicit val personRW: OptionPickler.ReadWriter[Person] = OptionPickler.macroRW[Person]
val personJson = …Run Code Online (Sandbox Code Playgroud) 我有这样的代码:
optionBoolean.getOrElse(false) && otherOptionBoolean.getOrElse(false)
Run Code Online (Sandbox Code Playgroud)
Scalastyle 告诉我它可以简化。如何?