Categories
Uncategorized

Do not forget to go study notes function before the foundation of learning functional programming

In the programming world has always been there is no one dominant style of programming, at least for now still contending Spring and Autumn, in addition to the well-known object-oriented programming as well as the growing popularity of functional programming, of course, this is also the focus of this series of articles.

More and more mainstream language in the design of almost without exception, will refer to functional properties (lambda expressions, native support for map, reduce …), and even object-oriented language Java8 slowly began to support functional programming so do not learn functional programming may be too late!

But before formal learning functional programming, and might already familiar with object-oriented programming bottom of my heart to do the next comparison, by comparing the way of learning, I believe you will gain full, so specially sorted out a series of articles on object-oriented language Go, inviting Jun Dramas.

    Guess go is not object-oriented language? Can Object-Oriented Programming?

    Detailed talk about the package go study notes how the matter

    go study notes of support and how to implement inheritance

    go study notes it never occurred to the pet store even spawned oriented programming interface?

    go study notes interface and the inaction of unintentional positive outcomes shade of the rule of empty interface

Go above-mentioned series of articles explaining the object-oriented language knowledge point, if the click does not support frames, you can focus on micro-channel public number “Snow Dream Inn technology” View History article, thank you for your attention and read again.

Biologists and mathematicians different positions

While the world is the same, but different people see things standing in their respective positions, the result will naturally thousand thousand faces, different.

Biologists will subconsciously grouped together in a plant or animal, object-oriented programming, too, with a series of abstract models to simulate the behavior of real-world laws.

Mathematicians have always been known for rigorous study, as the most important basic science, mathematics and the laws of induction and deduction corresponding methodology is functional programming, but not simulate reality the law is more likely to describe the creation of the law.

Standard functional programming with a strong mathematical color, fortunately, Go is not a functional language, so it is not necessarily limited to blame almost like think outside the box.

Briefly, functional programming has the following characteristics:

    Immutability: no state variables and variable objects

    Only one parameter function

    Pure function has no side effects

Excerpt from Wikipedia about functional programming there are so many words:

In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

The general meaning of the above is to say in English: functional programming of a computer program as a function of mathematical deduction, not a variable state variables do not object to express the relationship between the number and the number.

For more information, click access to relevant Wikipedia introduction to functional programming Functional programming is.

Functional programming standpoint and the starting point is a function of the complex function is a basic function of the law of formation through some combination of, the described process is a complex function of how to remove the reorganization process.

So let’s review the basic characteristics of one side while learning function, to lay the foundation for the next understanding functional programming, on the basis of language functions can go study notes refer to the basic grammar of particular concern What

Basic grammar functions and advanced features

Below four basic arithmetic, for example, through the basic grammar and text to explain the function of advanced features, and strive to do know these know why.

    the definition of normal function func

eval function defines the basic arithmetic operation rules, if not support the type of operation exception is thrown, the program terminates.

func eval(a, b int, op string) int {
    var result int
    switch op {
    case "+":
        result = a + b
    case "-":
        result = a - b
    case "*":
        result = a * b
    case "/":
        result = a / b
    default:
        panic("unsupported operator: " + op)
    }
    return result
}

When testing the operation is not defined modulo% operator, an exception is thrown, unsupported operator:%, explained only supports basic arithmetic operations.

func TestEval(t *testing.T) {
    // 3 -1 2 0 unsupported operator: %
    t.Log(
        eval(1, 2, "+"),
        eval(1, 2, "-"),
        eval(1, 2, "*"),
        eval(1, 2, "/"),
        eval(1, 2, "%"),
    )
}

    Multi-standard functions defined return value

Go language and other mainstream programming languages ​​obvious difference is, support for multi-function return values, usually the first value represents the real results are returned, the return value indicates whether the second error, which is unique on Go exception error design.

If returns normally, then there is no error, then the first value is a return to normal and the second result value is returned empty nil; if abnormal returns, the first special design value meaningless return, the return value of the second specific error messages, general non-nil.

func evalWithStandardStyle(a, b int, op string) (int, error) {
    switch op {
    case "+":
        return a + b, nil
    case "-":
        return a - b, nil
    case "*":
        return a * b, nil
    case "/":
        return a / b, nil
    default:
        return 0, fmt.Errorf("unsupported operator: %s", op)
    }
}

Eval function to write a real transformation Go program, then test again showed that no longer throws an exception but return to the default value of zero, and gives a brief description of the error message encountered no defined operator.

func TestEvalWithStandardStyle(t *testing.T) {
    // Success: 2
    if result, err := evalWithStandardStyle(5, 2, "/"); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }

    // Error: unsupported operator: %
    if result, err := evalWithStandardStyle(5, 2, "%"); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

    Other functions as an argument

The return value by more than the above example to solve the problems of the operators do not support being given to terminate the program, but does not really solve the problem, when and if they really want to make a non-predefined operation, the same is powerless!

Who told you the user rather than just a designer it!

So the stage to you, you are the main character, how you want to handle input on how to deal with how output, all logical transfer to the user, so there is no case can not meet the needs of the.

func evalWithApplyStyle(a, b int, op func(int, int) (int, error)) (int, error) {
    return op(a, b)
}

Operators from the original string string changes as a function func (int, int) (int, error), the stage to you, thanks to free play!

EvalWithApplyStyle internal direct call function op argument and returns a processing result of the function, the current demo complete the transfer of control to the function into the function op function parameters, to decide how to handle the actual situation according to the actual needs evalWithApplyStyle logic.

func divide(a, b int) (int, error) {
    return a / b, nil
}

func mod(a, b int) (int, error) {
    return a % b, nil
}

Their hands and clothing, easily define and divide division mod modulo arithmetic, the effect achieved at the next test.

func TestEvalWithApplyStyle(t *testing.T) {
    // Success: 2
    if result, err := evalWithApplyStyle(5, 2, divide); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }

    // Success: 1
    if result, err := evalWithApplyStyle(5, 2, mod); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

Test results are very satisfactory, not only the basic operations such as addition and subtraction, multiplication and division, modulo arithmetic can also be achieved before been unable to achieve!

This illustrates this approach as a function of parameters to fully mobilize the enthusiasm of the people’s labor, my mother no longer have to worry about me not implement complex functions of it!

    Anonymous functions can also be used as parameters

In general, when you call the function directly using the function name is called, it has a separate function reusability, but if this is a one-time function, then there is no need to define the function with a function name form.

Still above example, this time for operational rule number two is no longer the math, and this time we compare the maximum of two numbers, use the form of an anonymous function will be realized.

func TestEvalWithApplyStyle(t *testing.T) {
    // Success: 5
    if result, err := evalWithApplyStyle(5, 2, func(a int, b int) (result int, e error) {
        if a > b {
            return a, nil
        }
        return b, nil
    }); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

    Return value of the function may be a function

It is still the example above, if the function returns the results due immediately but does not require the user to wait when they feel the time is right and then calculate the return value, the function returns a value at this time is still the function can be helpful, that is the so-called lazy evaluation.

func evalWithFunctionalStyle(a, b int, op func(int, int) (int, error)) func() (int, error) {
    return func() (int, error) {
        return op(a, b)
    }
}

These functions may seem a little difficult to understand, in fact, with respect to the above example only changed the return value from the original (int, error) changed to func () (int, error), the rest were unchanged yo!

evalWithFunctionalStyle function is still the user’s home, and the only difference is that compared to the previous example, your home you call the shots, what they say goes completely when the referee is not run immediately after the results are announced.

func pow(a, b int) (int, error) {
    return int(math.Pow(float64(a), float64(b))),nil
}

func TestEvalWithFunctionalStyle(t *testing.T) {
    ef := evalWithFunctionalStyle(5, 2, pow)

    time.Sleep(time.Second * 1)

    // Success: 25
    if result, err := ef(); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

time.Sleep (time.Second * 1) on behalf of the demo code execution evalWithFunctionalStyle function may not calculate the final result immediately, wait time is right again by the user calling ef () function lazy evaluation.

// 1 1 2 3 5 8 13 21 34 55
//     a b
//       a b
func fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

    Function can act as a type

In the example described above can be explained as a return value of the function, the function parameters, return values ​​have parameters, so evalWithFunctionalStyle function looks more strenuous, the language type alias Go is born for simplicity, not to mention the first-Go function is citizens, of course, appropriate.

func evalWithFunctionalStyle(a, b int, op func(int, int) (int, error)) func() (int, error) {
    return func() (int, error) {
        return op(a, b)
    }
}

Then going to the argument of function func (int, int) (int, error) and the return value of the function func () (int, error) unified, the pitch function parameter and return value function is the only difference between the number of different parameters , so naturally think of Go function of variable length parameters associated syntax.

type generateIntFunc func(base ...int) (int, error)

Thus the reference function and the reference function can be replaced with generateIntFunc type function, then the transformation function evalWithFunctionalStyle.

func evalWithObjectiveStyle(a, b int, op generateIntFunc) generateIntFunc {
    return func(base ...int) (i int, e error) {
        return op(a, b)
    }
}

After transformation evalWithObjectiveStyle function looks relatively simple, showy flower seen by hard to say whether, or speak it with a test!

func TestEvalWithObjectiveStyle(t *testing.T) {
    ef := evalWithObjectiveStyle(5, 2, func(base ...int) (int,error) {
        result := 0
        for i := range base {
            result += base[i]
        }
        return result,nil
    })

    time.Sleep(time.Second * 1)

    // Success: 7
    if result, err := ef(); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

After the function alias does not affect the type of function is still functional programming, but mixed with some object-oriented flavor.

    Function type of interface can be achieved

After the type of function can be achieved by an alias interfaces, it can be regarded as one type to some extent, and therefore implementation of the interface is the logical thing.

func (g generateIntFunc) String() string {
    r,_ := g()
    return fmt.Sprint(r)
}

The sample code here for the type of String function generateIntFunc implement interface methods, may not have much practical significance, just to explain this knowledge and hard Coushang, the actual situation will definitely be different.

func TestEvalWithInterfaceStyle(t *testing.T) {
    ef := evalWithObjectiveStyle(5, 2, func(base ...int) (int,error) {
        result := 0
        for i := range base {
            result += base[i]
        }
        return result,nil
    })

    time.Sleep(time.Second * 1)

    // String: 7
    t.Log("String:", ef.String())

    // Success: 7
    if result, err := ef(); err != nil {
        t.Log("Error:", err)
    } else {
        t.Log("Success:", result)
    }
}

Get lazy evaluation of function variable ef can now call the String method, the object of which is the ability to have the final result turned out and run directly a function of the value of the same?

A little magical, is not yet understand what this operation, if there are bigwigs in Go wing it, brother grateful!

    Ripe closure

Function parameters, return value may be an additional function, the function may be passed as a reference as to the variable, there is also a simplified form anonymous functions, etc., in addition, a function of the type and the like can also be used to implement the interface characteristics it should be sufficient to explain the noble status of first-class citizens, right?

Such a powerful function characteristics, just a little combination will have a strong capability, and the Go language is not strictly functional language, syntax level is not too restrictive.

// 1 1 2 3 5 8 13 21 34 55
//     a b
//       a b
func fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

Fibonacci number fibonacci function return value is the real generator function, each call will generate a new Fibonacci numbers.

This is a simple example of the Go language implementation of closures, fibonacci function of the variable itself a, b is an internal anonymous function func () int referenced, and this reference is eventually users will continue to lead the initial call a, b variable has been occupied with, as long as continue to call this generator, Pei Fibonacci series of numbers would have been incremented.

// 1 1 2 3 5 8 13 21 34 55
func TestFibonacci(t *testing.T) {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Print(f(), " ")
    }
    fmt.Println()
}
func TestFibonacci(t *testing.T) {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Print(f(), " ")
    }
    fmt.Println()
}

Functional programming function entry summary

    Functions are first-class citizens, which function parameters, variables, function return value can be a function.

    Higher order function is a normal function of a combination of, parameters and return values ​​may be another function.

    Function is the basis of functional programming, functional programming support but not functional language.

    No purely functional programming rules, more flexibility and freedom, good readability.

If this article help you, please tap the touch of hands is recommended, otherwise also correct me please leave a message and, if necessary, public awareness of personal numbers, "Snow Dream Inn technology."

Leave a Reply