Scala loan template, optional function parameter

I have a loan template that applies the function n times, where "i" is an additional variable. "Sometimes," I want the passed function to have access to "i" .... but I do not want to require that all the passed functions require a parameter definition to accept "i". Example below ...

def withLoaner = (n:Int) => (op:(Int) => String) => { val result = for(i <- 1 to n) yield op(i) result.mkString("\n") } def bob = (x:Int) => "bob" // don't need access to i. is there a way use () => "bob" instead? def nums = (x:Int) => x.toString // needs access to i, define i as an input param println(withLoaner(3)(bob)) println(withLoaner(3)(nums)) 
+5
source share
1 answer
 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 .

+11
source

Source: https://habr.com/ru/post/896846/


All Articles