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

  • Learn Scala Programming
  • Slava Schmidt
  • 365字
  • 2021-06-10 19:35:51

Functions are traits

Each function in Scala implements a FunctionN trait, where N is an arity of the function. The zero-argument function is translated by the compiler to the implementation of Function0, of one argument—to Function1 and so on, up to Function22. This complexity is needed because of the static nature of the language. Does it mean it is not possible to define functions of more than 22 arguments? Well, it is always possible to define a function using currying or multiple parameter lists, so this is not really a limitation.

Function literals are just a syntactic sugar accepted by the compiler for developers' convenience. This is how the desugared signature of our previously defined Ackerman function looks:

val A: Function2[Long, Long, Long] = (m, n) =>
if (m == 0) n + 1
else if (n == 0) A.apply(m - 1, 1)
else A.apply(m - 1, A.apply(m, n - 1))

And the (simplified) definition of Function2 in the standard library is like this:

trait Function2[-T1, -T2, +R] extends AnyRef { self =>
def apply(v1: T1, v2: T2): R
...
}

Remember our co- and contravariance discussion in the previous chapter? Here we have it in action; the arguments are contravariant and the result type is covariant.

It turns out that the compiler rewrites our definition as an instance of an anonymous class implementing this trait:

val objectOrientedA: Function2[Long, Long, Long] = 
new Function2[Long, Long, Long] {
def apply(m: Long, n: Long): Long =
if (m == 0) n + 1
else if (n == 0) objectOrientedA(m - 1, 1)
else objectOrientedA(m - 1, objectOrientedA(m, n - 1))
}

And the instance of this class can then be passed over, assigned to a variable, stored into data structures, and so on. The FunctionN trait also defines a few helper methods that implement function-related functionality at the library level, as opposed to the language syntax. One example is a conversion of a normal function into the curried form, which for Function2[T1,T2,R] is defined as def curried: T1 => T2 => R = (x1: T1) => (x2: T2) => apply(x1, x2) 

scala> objectOrientedA.curried
res9: Long => (Long => Long)

This method is available for any function.

主站蜘蛛池模板: 翁牛特旗| 杨浦区| 金湖县| 银川市| 叶城县| 浪卡子县| 美姑县| 郸城县| 万宁市| 宜宾县| 黑河市| 沧州市| 海南省| 曲沃县| 勐海县| 桓台县| 深水埗区| 南丹县| 宝清县| 长白| 漯河市| 共和县| 怀远县| 镇安县| 木兰县| 弥勒县| 西乌珠穆沁旗| 蒲城县| 永德县| 苗栗县| 郴州市| 德昌县| 青铜峡市| 平遥县| 城步| 页游| 平罗县| 定边县| 彭州市| 布拖县| 靖安县|