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

Partial application and functions

Until now, the methods and variables were handled the same way by the compiler. Can we exploit the similarities further and return a method as a result of another method and store it into the variable? Let's give it a try:

scala> object Functions {
| def method(name: String) = {
| def function(in1: Int, in2: String): String = name + in2
| function
| }
| val function = method("name")
| }
function
^
On line 4: error: missing argument list for method function
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `function _` or `function(_,_)` instead of `function`.

Unfortunately, it didn't work. We tried to create and return a function from within a method and assign this function to a variable, but the compiler does not allow this. However, it gives us a useful hint about what we are doing wrong!

It turns out that functions and methods are different for the compiler and methods can only be passed in the form of an instance of the enclosing class. This distinction is related to the fact that everything in the JVM is represented as an instance of some class. Because of this, the methods we define become methods of the class, and methods are not first-class citizens in the JVM. Scala works around this approach by having a hierarchy of classes representing functions of different arities. Thus, in order for us to be able to return a method from another method, the former must become a function. And the compiler gave us a hint as to how to achieve this: by using _ (underscore) in the place where the parameters are expected.

scala> object Functions {
| def method(name: String) = {
| def function(in1: Int, in2: String): String = name + in2
| function _
| }
| val function = method("name")
| }
defined object Functions

The partial application can have two forms: a single underscore replacing the whole parameter list, or a single underscore replacing each parameter. Thus, for the partial application of the function we've just defined, both function _ or function(_,_) would be appropriate. 

The partial application syntax can be used to create shortcuts for functions defined elsewhere, by importing and partially applying them at the same time:

val next = Math.nextAfter _
next(10f, 20f)
val /\ = Math.hypot(_, _)
/\ (10 , 20)

In general, for the function of N parameters, the partial application means specifying 0 =< M < N parameters and leaving the rest undefined, basically applying the function to some part of the parameter list. This partial application gives a function of (N-M) parameters and the same type of result as the original function back. In our previous example, we defined M to be zero and thus the signature of the resulting function remained unchanged. But the very fact of there being a partial application has converted our method into the function, which allowed us to further work with it as with a value.

In the case, if 0< M <N,  the underscores go into the place of the parameters that are not applied at the moment:

def four(one: String, two: Int, three: Boolean, four: Long) = ()
val applyTwo = four("one", _: Int, true, _: Long)

We applied the first and third arguments and left the second and fourth unapplied. The compiler requires us to provide a type ascription for missing parameters in order to use it while inferring the type of the resulting function.

The parameter names defined for methods are lost during the partial application and so are default values. The repeated parameters are converted to the Seq.

主站蜘蛛池模板: 凉山| 保康县| 阳新县| 巴彦淖尔市| 濮阳县| 绥宁县| 宜丰县| 洞头县| 太谷县| 潮州市| 抚顺市| 彭州市| 西乌珠穆沁旗| 奈曼旗| 马山县| 武宁县| 常宁市| 黄大仙区| 治县。| 图片| 丰顺县| 黄骅市| 扶绥县| 清徐县| 武山县| 苍南县| 庆云县| 天峨县| 庆阳市| 商南县| 乐山市| 江孜县| 格尔木市| 澎湖县| 阳原县| 宁晋县| 托里县| 若尔盖县| 凤庆县| 濉溪县| 清丰县|