我对Scala相对较新。
尝试开发一种允许“连接”编程的模式。 目标是能够以类似方式的linux“管道”从左到右链接对数据的操作,同时拖动可能从其中一个方法返回的任何错误。所以在链的末尾有一个Either。
我无法将其归结为单个运算符 - 我似乎必须根据运算符右侧的方法进行区分 - 如果它返回一个简单的结果或已经包含在Either中的结果。
这里要求对现有库执行此操作的批评/提示/指示
由于
type PResult[R] = Either[String, R]
implicit class fromVal[A](val in: A) {
def |>[B](f: A => B): PResult[B] = Right(f(in))
def |>>[B](f: A => PResult[B]): PResult[B] = f(in)
}
implicit class fromEither[A](val in: PResult[A]) {
def |>[B](f: A => B): PResult[B] =
in match {
case Left(l) => Left(l)
case Right(r) => Right(f(r))
}
def |>>[B](f: A => PResult[B]): PResult[B] =
in match {
case Left(l) => Left(l)
case Right(r) => f(r)
}
}
val f1: Int => Int = _ + 2 //> f1 : Int => Int = <function1>
val f2: Int => PResult[Int] = { in => Right(in + 3) }
//> f2 : Int => piper.PResult[Int] = <function1>
22 |>> f2 |> f1 |>> f2 //> res0: piper.PResult[Int] = Right(30)
我认为类似的东西可以用于期货和其他结果可能成功或失败的事情。
我确实知道我的 |&gt; 和 |&gt;&gt; 与map和flatMap非常相似。
如果我将我尝试做的事情与理解进行比较 - 它们也不是同质的 - 你必须使用&lt; - 来处理包含在选项中的内容或其他内容和 = ,它只是一个计算。 那么我想念的是什么,可以改进什么呢?
答案 0 :(得分:1)
我认为你可以像这样重写第二个隐含的内容:
implicit class fromEither[A](val in: Either[String, A]) {
def |>[B](f: A => B) = in.right.map(f)
def |>>[B](f: A => Either[String, B]) = in.right.flatMap(f)
}
你也可以扩展AnyVal
,这应该稍微高效一点。我甚至不会定义第一个隐式类。在Right
中包装第一个元素并不是很麻烦,就像你cat somefile
一样。
请注意,实际上有一个类似于unix管道的API用于运行进程http://www.scala-lang.org/api/current/#scala.sys.process.package。
如果您想将它提升到一个新的水平,您可以查看迭代和枚举。见http://www.playframework.com/documentation/2.1.x/Enumeratees。它允许您执行类似strings |>> toInt &>> sum
的操作,其中strings
枚举一些字符串,toInt
将每个字符串转换为整数,sum
将它们加在一起。