golang-functional Programming (closures)

Source: Internet
Author: User
Tags mathematical functions what magic
This is a creation in Article, where the information may have evolved or changed.

GitHub:https://github.com/ZhangzheBJUT/blog/blob/master/closure.md


An introduction to Functional programming

In the past 10 years, object-oriented programming has been so much so that in college education, teachers will only teach us two programming models, process-oriented and object-oriented. It is not known that functional programming has been around for decades before object-oriented thinking is produced. Let's look back at this ancient and modern programming model and see what magic is pulling this concept into our sights again in the 21st century.

With the increase in hardware performance and improvements in compiler technology and virtual machine technology, some of the dynamic languages that were once constrained by performance issues are beginning to be noticed, and languages such as Python, Ruby, and Lua are beginning to emerge in the application. Dynamic language has become a popular programming language for many people because of its convenient and fast development, and the functional programming has come into our view again with the popularity of dynamic language.

What exactly is functional programming?

In Wikipedia, there is a detailed introduction to functional programming. The definition of functional programming on a wiki:

In computer science, functional programming are a programming paradigm that treats computation as the evaluation of Mathema Tical functions and avoids state and mutable data.

A simple translation, that is, functional programming is a programming model, he regards computer operations as mathematical functions in the calculation, and avoids the concept of state and variable.

Two-closed package

Closures are often used in function programming, what are closures? How does it come into being and what problem is it used to solve? The literal definition of closures is given: closures are entities that are composed of functions and their associated reference environments (i.e., closures = function + reference environment). This is literally hard to understand, especially for programmers who have been programming with imperative languages.

Closures are just like functions in form and expression, but are not actually functions. Functions are executable code that is determined after the function is defined and does not change at execution time, so there is only one instance of a function. Closures can have multiple instances at run time, and different reference environments and the same combination of functions can produce different instances. The so-called reference environment is a collection of all active constraints at a point in the execution of a program. The constraint refers to the relationship between the name of a variable and the object it represents. So why combine the reference environment with the function? This is mainly because in languages that support nested scopes, it is sometimes not straightforward to determine the reference environment of a function directly. Such a language generally has such a feature:

A function is a class citizen (first-class value), which is a function that can be used as the return value or parameter of another function, as well as as a variable value.
Functions can be defined in a nested definition, meaning that another function can be defined inside a function.

In object-oriented programming, we transmit the object, that in functional programming, to do is to pass the function, said the term, called him a higher-order function. In mathematics and computer science, higher-order functions are functions that meet at least one of the following conditions:

Accept one or more functions as input
Output a function

In functional programming, the function is the basic unit, the first type, and he is almost used for everything, including the simplest calculations, and even the even variables are replaced by calculations.

closure summary:
function is just a piece of executable code, after compiling" cured ", each function in memory only one instance, The function can be executed by getting the entry point of the function. In a functional programming language, a function is a first-class citizen: A primary object, we do not need a function pointer, as in imperative language, a delegate action function, a function can be a parameter or a return value of another function, can be assigned to a variable. Functions can be nested defined, that is, within one function can define another function, with the structure of nested functions, the closure problem arises. such as:

package mainimport (" FMT ") func adder () func (int) int {sum: = 0 Innerfunc: = func (x int) int {  sum + = x return sum} return Innerfunc}func main () {pos, neg: = Adder (), adder () for I: = 0; I < 10; i++ {fmt. Println (POS (i), neg ( -2*i))}}  

In this program, the function innerfunc is an inline function of the function adder and is the return value of the Adder function. We notice a problem: The local variable referenced in the outer function in the inline function Innerfunc Sum,go will handle this problem? Let's start by looking at the results of this code:

0 0  1 -2  3 -6  6 -12   10 -20  15 -30  21 -42  28 -56  36 -72  45 -90  

Note:go cannot explicitly nest defined functions inside a function, but you can define an anonymous function. as shown above, we define an anonymous function object, assign it to Innerfunc, and return it as the return value.

When the Adder function is called with a different parameter (POS (i), neg (i)), the resulting result is isolated, that is, each call to Adder returns the function that generates and saves a new local variable sum. In fact, the Adder function here is to return a closed packet.
This is the closure in go, a function and an entity that is combined with its associated reference environment. A famous saying about closures: objects are data with behaviors, and closures are the act of attaching data.

Three-closed package use

Closures are often used for callback functions, and when IO operations (such as fetching data from the network, file reads and writes) are completed, certain operations are performed on the obtained data, which can be passed to the function object for processing.

In addition, in some common operations there are often different special operations, and these differentiated operations can be encapsulated with a function. Look at the following example:

Package Mainimport ("Errors" "FMT") type Traveser func (ele interface{})/* Process: Encapsulates a common slice array operation */func process (array interface{}, Traveser Traveser) Error {if array = = nil {return errors. New ("Nil Pointer")} var length int//An array of lengths of switch array. (type) {case []int:length = Len (array. ( []int)] case []string:length = Len (array. ( []string)] case []float32:length = Len (array. ( []float32)] Default:return errors. New ("Error type")} if Length = = 0 {return errors.    New ("Len is zero.") } traveser (Array) return nil}/*: Sort the array element in ascending order */func sortbyascending (Ele interface{}) {intslice, OK: = Ele. ( []int) if!ok {return} length: = Len (intslice) for I: = 0; i < length-1;                i++ {ischange: = False for J: = 0, J < Length-1-i, + j + {if INTSLICE[J] > intslice[j+1] { Ischange = True Intslice[j], intslice[j+1] = intslice[j+1], IntSLICE[J]}} if Ischange = = false {return}}}/* specific actions: Sort the array elements in descending order */func sort Bydescending (Ele interface{}) {intslice, OK: = Ele. ( []int) if!ok {return} length: = Len (intslice) for I: = 0; i < length-1;                i++ {ischange: = False for J: = 0, J < Length-1-i, + j + {if INTSLICE[J] < intslice[j+1] {        Ischange = True Intslice[j], intslice[j+1] = intslice[j+1], Intslice[j]} If Ischange = = false {return}}}func main () {intslice: = make ([]int, 0) Intslice = Append (Intslice, 3, 1, 4, 2) Process (Intslice, sortbydescending) fmt. Println (Intslice)//[4 3 2 1] Process (Intslice, sortbyascending) fmt. Println (Intslice)//[1 2 3 4] Stringslice: = Make ([]string, 0) Stringslice = append (Stringslice, "Hello", "World", " )/* Specific: Use anonymous function to encapsulate output operation */Process (Stringslice, func (Elem interface{}) {if slice, OK: = Elem. ([]string); ok {for index, value: = Range Slice {fmt. Println ("index:", Index, "value:", Value)}}) Floatslice: = Make ([]float32, 0) Floatslice        = Append (Floatslice, 1.2, 3.4, 2.4)/* Specific actions: Use anonymous functions to encapsulate custom actions */Process (Floatslice, func (Elem interface{}) { If slice, OK: = Elem. ([]float32); OK {for index, value: = Range Slice {Slice[index] = value * 2}}) F Mt. Println (Floatslice)//[2.4 6.8 4.8]}

Output Result:

[4 3 2 1]   [1 2 3 4]index: 0   value: helloindex: 1   value: worldindex: 2   value: china[2.4 6.8 4.8]

In the above example, the process function is responsible for the operation of the slice (array) data, in the operation of the Slice (array), the first to do some parameter detection, such as whether the pointer is empty, the length of the array is greater than 0. These are common operations for manipulating data. Specific to the data can have their own special operations, including sorting (ascending, descending), output and so on. For these special operations, the function object can be used for encapsulation.
look at the example below, this example doesn't make any sense, just to illustrate how closures are used.

Package Mainimport ("FMT") type Filterfunc func (ele interface{}) interface{}/* Public operations: Special Operations on data */func the interface {}, Filterfunc Filterfunc) interface{} {slice: = make ([]int, 0) Array, _: = arr. ([]int] for _, Value: = Range AR Ray {integer, OK: = Filterfunc (value). ( int) If OK {slice = append (slice, Integer)}} return slice}/* specific operation: Odd variable even (this can be done without the interface type, directly type int) */func evenfilter (Ele interface{}) interface{} {integer, OK: = Ele. ( int) If OK {if integer%2 = = 1 {integer = integer + 1}} return integer}/* specific operation: even variable odd (This can be used without the interface type, directly using the int type) */func oddfilter (Ele interface{}) interface{} {integer, OK: = Ele. (    int) If OK {if integer%2! = 1 {integer = integer + 1}} return Integer}func main () { Sliceeven: = Make ([]int, 0) Sliceeven = append (Sliceeven, 1, 2, 3, 4, 5) Sliceeven = Data (Sliceeven, Evenfilter). ([]int) fmt. Println (Sliceeven)//[2 2 4 4 6]   Sliceodd: = Make ([]int, 0) sliceodd = append (sliceodd, 1, 2, 3, 4, 5) sliceodd = Data (sliceodd, Oddfilter). ([]int) fmt. Println (sliceodd)//[1 3 3 5 5]}

Output Result:

[2 2 4 4 6]  [1 3 3 5 5]

Data is used as a public function, and then two specific special functions are defined: even and odd filters, which define the specific operation.

Iv. Summary

The use of closures in the example above is somewhat similar to the template pattern in object-oriented design mode, where the common behavior execution sequence is defined in the parent class, and then the subclass implements the specific operation by overloading the parent class, and in the go language we use closures to achieve the same effect.
In fact, the most convenient way to understand the closure is to consider the closure function as a class, a closure function call is to instantiate a class (in Objective-c, the closure is implemented by the class), and then you can see from the perspective of the class which is "global variables", which is "local variables." For example, in the first example, POS and neg instantiate two "closure classes", each of which has a "closure global variable" sum in this "closure class". So it's good to understand the results of the return.

Reference:
Http://www.ibm.com/developerworks/cn/linux/l-cn-closure/index.html
Http://www.cnblogs.com/kym/archive/2011/03/07/1976519.html


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.