Concise syntax for function composition in Scala?

让人想犯罪 __ 提交于 2019-12-23 08:30:22

问题


I'm learning Scala and ran across the following task - if string is blank then return null, otherwise uppercase it.

There are two functions in Apache Commons that composed together solves the problem. In Haskell I'd just write:

upperCaseOrNull = StringUtils.stripToNull . StringUtils.upperCase

However I can't find a way to do an easy and clean function composition in Scala. the shortest way I found is as follows:

def upperCaseOrNull (string:String) = StringUtils.stripToNull (StringUtils.upperCase(string))
def upperCaseOrNull = StringUtils.stripToNull _ compose StringUtils.upperCase _

Does Scala offer a more concise syntax, possibly without all those underscores?


回答1:


Haskell is a master of extreme compactness for a few things it really cares about. So it's pretty much impossible to beat. If you are doing so much function composition that the overhead really gets in your way (personally, I'd be a lot more troubled by repeating StringUtils.!), you can do something like

implicit class JoinFunctionsCompactly[B,C](g: B => C) {
  def o[A](f: A => B) = g compose f
}

so now you only have four extra characters (_ twice) over Haskell.




回答2:


I wouldn't claim a task be simple if null's are involved. Why would you need null if None in Scala would do? I think that due to null being returned the function is not very compose-friendly.

Once you transform StringUtils.stripToNull to return None for null and Some otherwise, you could then use scala.Option.map and execute it with _.toUpperCase - see the scaladoc for scala.Option where this particular example is discussed.

One might also suggest something as follows:

scala> def upperCaseOrNone = (s: String) => Option(s).fold(s) { _.toUpperCase }
upperCaseOrNone: String => String



回答3:


It is possible to make composition slightly more compact:

Using andThen

To get it down to a single underscore (even with more than two functions composed):

def upperCaseOrNull = StringUtils.upperCase _ andThen StringUtils.stripToNull

More general case with three functions:

def fgh  = h _ andThen g andThen f

Using a helper function

If f, g and h are functions taking one String parameter and returning a String:

def fgh = composeMany[String](f, g, h)

Where the composeMany function looks like this:

def composeManyHelper[T](composed: T => T, funcs: Seq[T => T]): T => T = {
  if (funcs.isEmpty) {
    composed
  } else {
    composeManyHelper[T](funcs.head compose composed, funcs.tail)
  }
}

// Take zero or more functions that take a param of type T and return a value of type T,
// and return a function that is the composition of all the functions
def composeMany[T](funcs: (T => T)*): T => T = {
  composeManyHelper[T](identity[T], funcs.reverse)
}


来源:https://stackoverflow.com/questions/22410045/concise-syntax-for-function-composition-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!