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

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.

主站蜘蛛池模板: 昌图县| 江城| 玉林市| 尚义县| 孝义市| 淮滨县| 海南省| 隆昌县| 永胜县| 无棣县| 花莲县| 阳新县| 凌海市| 萨迦县| 丹巴县| 惠水县| 柯坪县| 陆丰市| 闽清县| 大邑县| 南召县| 响水县| 萝北县| 龙岩市| 婺源县| 宿州市| 泾川县| 正阳县| 新乐市| 安丘市| 且末县| 迁安市| 沧州市| 柳河县| 乐都县| 隆安县| 遂宁市| 沛县| 乌拉特前旗| 博乐市| 兴山县|