Implementing ifTrue, ifFalse, ifSome, ifNone, etc. in Scala to avoid if(…) and simple pattern matching

前端 未结 3 609
夕颜
夕颜 2020-12-08 17:44

In Scala, I have progressively lost my Java/C habit of thinking in a control-flow oriented way, and got used to go ahead and get the object I\'m interested in first, and the

3条回答
  •  春和景丽
    2020-12-08 18:28

    You may be looking at the problem too specifically. You would probably be better off with the pipe operator:

    class Piping[A](a: A) { def |>[B](f: A => B) = f(a) }
    implicit def pipe_everything[A](a: A) = new Piping(a)
    

    Now you can

    ("fish".length > 5) |> (if (_) println("Hi") else println("Ho"))
    

    which, admittedly, is not quite as elegant as what you're trying to achieve, but it has the great advantage of being amazingly versatile--any time you want to put an argument first (not just with booleans), you can use it.

    Also, you already can use options the way you want:

    Option("fish").filter(_.length > 5).
      map (_ => println("Hi")).
      getOrElse(println("Ho"))
    

    Just because these things could take a return value doesn't mean you have to avoid them. It does take a little getting used to the syntax; this may be a valid reason to create your own implicits. But the core functionality is there. (If you do create your own, consider fold[B](f: A => B)(g: => B) instead; once you're used to it the lack of the intervening keyword is actually rather nice.)


    Edit: Although the |> notation for pipe is somewhat standard, I actually prefer use as the method name, because then def reuse[B,C](f: A => B)(g: (A,B) => C) = g(a,f(a)) seems more natural.

提交回复
热议问题