1

我对 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)

我认为类似的东西可以用于期货和其他结果可能是成功或失败的事情。

我确实意识到我的|>|>>与 map 和 flatMap 非常相似。

如果我将我正在尝试做的事情与理解进行比较 - 它们也不是同质的 - 你必须使用<-用于包装在选项或其他东西中的东西和=它只是一个计算。那么我错过了什么,有什么可以改进的?

4

1 回答 1

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

如果你想更上一层楼,你可以看看 iteratees 和 enumeratees。请参阅http://www.playframework.com/documentation/2.1.x/Enumeratees。它允许你做这样的事情strings |>> toInt &>> sumstrings枚举一些字符串,toInt将它们中的每一个转换为整数sum并将它们加在一起。

于 2013-08-06T05:21:29.940 回答