3

使用 JodaTime,尝试将 List[LocalDate] 转换为 Tuple2[JodaTime, JodaTime] 以便我可以像这样进行多重分配:

val(expire, now) = 
  List(row.expireDate, new JodaDate) zip (_.toDateTimeAtStartOfDay.getMillis)

这当然不会编译。是否有类似简洁的方法来完成上述操作?我知道我可以手动完成:

val(expire, now) = 
  (row.expireDate.toDateTimeAtStartOfDay.getMillis, 
   new JodaDate().toDateTimeAtStartOfDay.getMillis)

但这有点难看

4

4 回答 4

10
val Seq(expire, now) = 
  Seq(row.expireDate, new JodaDate).map(_.toDateTimeAtStartOfDay.getMillis)
于 2012-07-06T14:06:56.767 回答
4

您想要的(假设您不想转换到Seq路由)是Scalaz 的元组Bifunctor实例(不在标准库中)。有了它,您可以编写以下内容:

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> val cap = (_: String).toUpperCase
cap: String => java.lang.String = <function1>

scala> val removeLs = (_: String).replaceAll("l", "")
removeLs: String => java.lang.String = <function1>

scala> cap <-: ("hello", "world") :-> removeLs
res0: (java.lang.String, java.lang.String) = (HELLO,word)

或者,在您的情况下:

val f = (_: JodaDate).toDateTimeAtStartOfDay.getMillis
val (expire, now) = f <-: (row.expireDate, new JodaDate) :-> f
于 2012-07-06T14:08:35.150 回答
2
val Seq(a, b) =
  Seq("a", "b").map(_.toUpperCase)

println("a, b = %s, %s".format(a, b)) // a, b = A, B
于 2012-07-06T14:07:48.443 回答
1

如果你想保持使用元组的类型安全(记住,当取消应用 a 时Seq,编译器不会检查长度),你可以编写一个包装器来添加一个标准库中不可用的函数,它会让你映射过去一个元组。

在使用单个函数映射两个元素的情况下,因为 aTuple2[A, B]有两个类型参数,所以实现这项工作的关键是需要证明AB是相同类型。为此,需要一个类型为隐式的参数B =:= A;如果类型确实相等,编译器将提供 type 的函数B => A

class Tuple2Wrapper[A, B](t: (A, B)) {
  def bimap[C, D](f: A => C, g: B => D): (C, D) = (f(t._1), g(t._2))
  def <-:->[C](f: A => C)(implicit ev: B =:= A): (C, C) = bimap(f, f compose ev)
}

implicit def tuple2Tuple2Wrapper[A, B](t: (A, B)) = new Tuple2Wrapper(t)

scala> (1, 1) <-:-> (_ + 1)
res1: (Int, Int) = (2,2)

Tuple2如果根据 Scalaz 的Bifunctor特征来实现,这可以以更通用和更有用的方式完成(适用于更多类型,而不仅仅是)。

于 2012-07-06T15:50:53.207 回答