Since it is functional programming, it is naturally unavoidable to know more about the function:
Methods are not equal to functions (function)
The method is not a function but can be converted into a function, can be converted by hand or automatically converted by the compiler (compiler) in appropriate cases. A reverse conversion is not a function that cannot be converted to a method. Let's take a look at the following example:
1 scala> def amethod (x:int): int = x +2amethod: (x:int) Int34 Scala> ; Val afunction = (x:int) + x +5 afunction:int = Int = <function1>
Amethod and afunction are different in type. And look at the following:
1 scala> afunction2 res0:int = Int = <function1>34 scala> Amethod 5 for method Amethod; 6 This method with ' _ ' If you want to treat it as a partially applied function7 Amethod
The reference method must provide a complete list of parameters, and the reference function is not required. Convert the method into a function? In the parameter position with _ to convert:
1 scala> val tofunction = Amethod _2 tofunction:int = Int = <function1>3 4 scala> tofunction5 res2:int = Int = <function1>
The function is characterized by amethod conversion into function tofunctions.
We call the function "first class value", which can be used as the parameter or return value of a higher-order function. However, the method is not a "first class value" and cannot be used as a parameter. So how do you explain the code in the example below?
1def main (args:array[string]): Unit = {2println (FormatResult ("absolute value", 42, ABS))3println (FormatResult ("factorial", 7, factorial))4println (FormatResult ("Increment", 7, (x:int) = x + 1))5println (FormatResult ("Increment2", 7, (x) = x + 1))6println (FormatResult ("Increment3", 7, x = x + 1))7println (FormatResult ("Increment4", 7, _ + 1))8println (FormatResult ("Increment5", 7, X = = {Val r = x + 1; R}))9}
Here ABS, factorial are the methods. Is it OK to pass in the higher order function FormatResult? Here is the result after the run:
1 The absolute value of-42 is2 the factorial of 7 are 50403 The increment of 7 is 84 The Increment2 of 7 is 85 The Increment3 of 7 are 86 The increment4 of 7 is 87 the INCREMENT5 of 7 is 8
Nothing wrong. Can the method be used as an incoming parameter? In fact, this program is automatically converted by the compiler at compile time. Scala's compilers can convert methods to functions where functions are needed.
functions are normal objects.
Here is a function text:
1 scala> (A:int, B:int) + A + b2 res4: (int, int) + int = <function2>
The compile-time compiler translates it into the following code:
1 New function2[int, int, int] {2 def apply (a:int, b:int) = a + b3 }
Here Function2 is the Scala language standard class object, Res4 (1+2) ===> addthem.apply
polymorphic functions
To demonstrate Scala's polymorphic functions, let's start with one of the following examples: Find the position of the first match number from an array of integers:
1def findfirstint (Arr:array[int], target:int): Int = {2def loop (idx:int): Int =idx Match {3 CaseLif(l >= arr.length)-1//indicate not found4 CaseIif(arr (i) = = target) =idx5 Case_ = = Loop (idx + 1)6 }7Loop (0)8}//> FindFirst: (Arr:array[int], target:int) Int9Findfirstint (Array (2,4,3,9,0), 3)//> res53:int = 2TenFindfirstint (Array (2,4,3,9,0), 7)//> Res54:int =-1
Find the location of the first matching string from a string array:
1def findfirststring (arr:array[string], target:string): Int = {2def loop (idx:int): Int =idx Match {3 CaseLif(l >= arr.length)-1//indicate not found4 CaseIif(arr (i) = = target) =idx5 Case_ = = Loop (idx + 1)6 }7Loop (0)8}//> Findfirststring: (arr:array[string], target:string) Int9Findfirststring (Array ("Hello", "My", "World"), "my")Ten //> res55:int = 1 OneFindfirststring (Array ("Hello", "My", "World"), "Yours") A //> Res56:int =-1
This function has many similarities to the above example of an array of integers, or is basically consistent. This allows us to abstract the common points through polymorphic functions:
1def Findfirsta[a] (arr:array[a],target:a) (equ: (a,a) = Boolean): Int = {2def loop (idx:int): Int =idx Match {3 CaseLif(l >= arr.length)-1//indicate not found4 CaseIif(Arr (i), target) = (EQU)idx5 Case_ = = Loop (idx + 1)6 }7Loop (0)8 9}//> Findfirsta: [A] (Arr:array[a], target:a) (equ: (A, a) = = Boolean) IntTenFindfirsta[int] (Array (2,4,3,9,0), 3) ((x, y) = = =y) One //> res57:int = 2 AFindfirsta[string] (Array ("Hello", "My", "World"), "My") ((x, y) = = =y) - //> res58:int = 1
Findfirsta is a polymorphic function. A is a type variable. We can say that Findfirsta is a polymorphic function for type variable A. Note that we have added a parameter list to Findfirsta-(equ: (a,a) = Boolean). This is because we are not sure about the type of a. Then we have to provide a type of contrast function. We can use Findfirsta to manipulate integers and strings. We can also operate on other types as long as we can provide that type of comparison function.
The white point of functional programming is the fiddling function. The process of programming is accomplished by putting the function over. The following example can be a clue:
A pure function is partially functional (partially apply): One parameter can be divided multiple times per function (apply) for a multiple-entry parameter
1 def Partialapply[a,b,c] (a:a, F: (B,c) and C): B + = C
By using the function partialapply, you can divide a two-entry function f into its parameters two times: reference partialapply is a function of parameter A, which is to form a functions that require parameter B.
Two parameters function (apply) One of them, so called part effect. How to achieve:
1 def Partialapply[a,b,c] (a:a, F: (A, B) + C): B + = c = (b:b) + F (A, B)2 // ; Partialapply: [A, B, C] (a:a, F: (A, b) = = c) B = + C
We know that the result of partialapply is a function that returns C as a parameter B. So find a way to get started on the matching type style. You can express this result directly with a function literal: Give me a b=b, I return to you a c=f (a, b); a typical lambda expression. Use a practical example to demonstrate:
1 def addtwoparams (a:int, b:int) = a + b //> Addtwoparams: (a:int, B:int) Int2 addtwoparams (2,5) //> res59:int = 73 val applyonce = partialapply (2, Addtwoparams) //> applyonce : int = int = <function1>4 Applyonce (5) //> res60:int = 7
Addtwoparams is a two-entry function, Applyonce is a function to the Addtwoparams function after a parameter 2, and then with the parameter 5 and applyonce after the result equals 7. = Addtwoparams (2,5). Why is it so much harder to change the function? In fact, this kind of function deformation is very common in functional programming, and it is a skill that the function combination (functional composition) must master.
Function transformation is a common technique in functional programming. The Curry function below turns the functions of an n input parameter into an n-th effect of a parameter:
F (a,b,c,... N) = f (a) (b) (c) ... (n) = a = + b and c = ... = n
1
The function Currytwo converts a function of two arguments into a parameter to return another function that is also a parameter. Use the function text to implement the Currytwo after using it for demonstration (note the type of return style):
1def Currytwo[a,b,c] (f: (A, B) + c): A = = (A:A) = ((B:B) +F (A, b))2 //> Currytwo: [A, B, C] (f: (A, B) and c) A = (b = c)3Val curriedfunction = Curry (addtwoparams)//> curriedfunction:int = (int = int) = <function1>4Val curryonce = curriedfunction (2)//> curryonce:int = Int = <function1>5Curryonce (5)//> res61:int = 7
Turn the addtwoparams into Curriedfunction int=> (int=>int). You can immediately see that you need to fill in the input parameters two times. When we encounter this problem of function morphing, we usually try to match the function's result type style (type signature) with the function text.
Uncurry is the inverse of curry: return the curry function to the multi-parameter function: a = = B and c = ... = = N = f (a,b,c,... N)
1 def uncurry[a,b,c] (f:a = B and C): (b) + C
Combine the examples above to demonstrate the implementation and use of Uncurry functions:
1 def uncurry[a,b,c] (f:a = B and C): (b) + = (a:a, b:b) = ( f (A)) (b)2 // C6>> Uncurry: [A, B, c] (f:a = (b = c)) (A, B) and C3 val uncurriedfunction = Uncurry (Currie dfunction)//> Uncurriedfunction : (int, int) = = Int = <function2>4 uncurriedfunction (2,5) // > res62:int = 7
Uncurriedfunction changed back again.
Finally, an example of a function combination is demonstrated:
1 def compose[a,b,c] (f:b = c, g:a = B): A = C
Compose is the combination of the F and G two functions into another function. Take a look at the following implementations and usage demonstrations:
1def compose[a,b,c] (f:b = c, g:a = B): A = = c = (a:a) = =F (g (a))2 //> Compose: [A, B, c] (f:b = c, g:a = B) A = C3Val fadd = (x:int) + x + 2//> fadd:int = Int = <function1>4Val Fmul = (y:int) = y * 5//> fmul:int = Int = <function1>5Val Multhenadd = Compose (Fadd,fmul)//> multhenadd:int = Int = <function1>6Multhenadd (2)//> Res63:int =
A new function is formed by combining the Fadd,fmul together. Multhenadd (2) = (2 * 5) + 2
If you re-write the image a little:
1 (Fadd compose Fmul) (2) // > Res64:int = 2 (Fmul compose Fadd) (2) // > Res65:int =
Note the compose right side of the hand associate: Fadd compose Fmul first operation Fmul the result input fadd. Design another left correlation function andthen:
1 def andthen[a,b,c] (f:a = B, g:b = c): A + c = (a:a) = g (f (A))2 //< /c4>> Andthen: [A, B, c] (f:a = b, g:b = c) A = C3 (Fadd andthen Fmul) (2) //< /c9>> Res66:int =
Consider the meaning of this: Fadd and Fmul may be large functions of thousands of lines of code, and we can easily connect them together, just to match the type.
Functional Programming (4)-delve into the Scala function class