def withLoaner(n: Int) = new { def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n") def apply(op: () => String) : String = apply{i: Int => op()} }
(not sure how it relates to the loan template)
Change A little explanation on request in the comment.
You do not know what you know and do not know about scala, and that you do not understand in this code. so sorry if i'm just carrying the obvious.
Firstly, the scala program consists of attributes / classes (also a Singleton object) and methods. Everything that is done is done using methods (leaving the constructor aside). Functions (unlike methods) are instances (subtypes) of various signs of FunctionN (N is the number of arguments). Each of them has an applicable method, which is the actual implementation. If you write
val inc = {i: Int => i + 1}
he responds
val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1}
(defines an anonymous class extending Function1 , with the given apply method and instantiation)
Thus, writing a function has more weight than a simple method. Also, you cannot overload (several methods with the same name, differing signatures, only what I did above), and also not use named arguments or the default value for the arguments.
On the other hand, functions are values โโof the first classes (they can be passed as arguments returned as a result), but methods are not. If necessary, they are automatically converted to functions, but some edge cases may occur. If a method is intended solely for use as a function value, and not for calling as a method, it is better to write a function.
The function f with its apply method is called with f(x) , not f.apply(x) (which also works), because the scala desugars function calls the notation for the value (the value followed by brackets and 0 or more arguments) to the call to the apply method. f(x) is the syntactic sugar for f.apply(x) . This works regardless of type f , it should not be one of FunctionN .
What is done in withLoaner returns an object (of an anonymous type, but one could define the class separately and return an instance of it). The object has two apply methods, one accepts Int => String , the other accepts () => String . When you execute withLoaner(n)(f) , it means withLoaner(n).apply(f) . The appropriate application method is selected if f is of the appropriate type for one of them, otherwise an error is compiled.
Just in case, you are surprised that withLoaner(n) does not mean withLoaner.apply(n) (or it will never stop, it can mean withLoaner.apply.apply(n) ), since withLoaner is a method, not a value .