官术网_书友最值得收藏!

Partial functions

The possibility of having additional methods gives a way do define concepts that would be hard to state otherwise, at least without extending the language itself. One such example is partial functions. A partial function is a function that is undefined for some values of its arguments. The classical example is a division that is not defined, for the divider equals zero. But actually, it is possible to have arbitrary domain rules that make some function partial. For instance, we could decide that our string reverse function should be undefined for empty strings.

There are a couple of possibilities for implementing such constraints in a program:

  • Throw an exception for arguments for which the function is not defined
  • Constrain the type of an argument so that it is only possible to pass a valid argument to the function, for example using refined types
  • Reflect the partiality in the return type, for example using Option or Either

There are obvious tradeoffs related to each of these approaches and in Scala, the first one is preferred as most natural. But, to better model the partial nature of the function, there is a special trait available in the standard library: 

trait PartialFunction[-A, +B] extends (A => B)

The key difference to normal function is that there is an additional method available that allows us to check whether the function is defined for some argument or not:

def isDefinedAt(x: A): Boolean

This allows the user of the function to do something different for "invalid" input values.

For example, let's imagine we've invented a very efficient method to check if a string is a palindrome. Then we could define our reverse function as two partial functions, one that is only defined for palindromes and does nothing and another that is defined only for non-palindromes and does the actual reverse action:

val doReverse: PartialFunction[String, String] = {
case str if !isPalindrome(str) => str.reverse
}
val noReverse: PartialFunction[String, String] = {
case str if isPalindrome(str) => str
}
def reverse = noReverse orElse doReverse

Here we're using syntactic sugar again to define our partial functions as a pattern match and compiler creates isDefinedAt method for us. Our two partial functions are combined into the total function using the orElse method.

主站蜘蛛池模板: 望城县| 罗平县| 澳门| 洞头县| 黄龙县| 竹北市| 白城市| 南乐县| 桦南县| 宁晋县| 昌都县| 咸宁市| 临颍县| 噶尔县| 五常市| 互助| 连平县| 枣强县| 东方市| 密云县| 栖霞市| 镇安县| 寿宁县| 华阴市| 上蔡县| 和政县| 伊春市| 郓城县| 舒兰市| 鄢陵县| 南昌市| 镶黄旗| 横峰县| 苍山县| 冷水江市| 普定县| 高邮市| 广安市| 天祝| 察雅县| 邵东县|