Monday, 2 February 2015

[Programming] Closure

Closure /ˈkləʊʒə/ sự đóng kín (Việt sub: cờ lâu giơ)

Là một khái niệm phổ biến ở các ngôn ngữ lập trình hàm (functional programming language như LISP, Scheme, ...) nhưng cũng có thể thấy ở Javascript,Ruby, Go, Object C, hay hỗ trợ 1 phần ở python2 và hỗ trợ hoàn toàn ở python3... (nhưng không có trong C, Java). Các ngôn ngữ nào cho phép trả về giá trị là một function thì có thể sẽ hỗ trợ closure.

Để tránh sử dụng wikipedia, sau đây là các định nghĩa closure từ document chính thức của một số ngôn ngữ lập trình:

Go đưa ra khái niệm ở dạng mô tả như sau trong gotour:
Một closure là một function (hàm) mà reference (tham chiếu) đến các biến ở ngoài body của nó. Function này có thể truy cập và thay đổi các biến mà nó đã reference. Có thể nói function "bound"(đã gắn) đến các biến.

EMACS LISP:
Một closure là function mà nó "mang theo" một bản ghi về "môi trường lexical" đã tồn tại khi hàm đó được định nghĩa.

Javascript:
Closure là function mà nó "tham chiếu"(refer) đến các biến độc lập. Hay nói cách khác, function ấy có khả năng "nhớ' về môi trường mà nó đã được tạo.

Dễ hiểu nhất là phân tích đoạn code sau:


func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }

}

func main() {
    pos, neg := adder(), adder() // trả về 2 closure và gán cho 2 biến pos, neg
    pos(1) // giá trị sum gắn với function pos = 0 + 1 = 1 (nói đầy đủ là function mà biến pos bind tới)
    neg(-3) // sum gắn với function neg = 0 + (-3) = -3
    fmt.Println(pos(2)) // sum gắn với function pos = (1 + 2) = 3
    fmt.Println(neg(-3)) // sum gắn với neg = (-3 + -3) = -6
}
Mỗi lần gọi hàm adder(), nó sẽ trả về 1 closure, mỗi closure này sẽ "bound"/"carry"/mang theo một biến sum riêng.
Chạy code ở đây để thấy kết quả: http://play.golang.org/p/yVUqskbaEf
Ví dụ gốc ở: https://tour.golang.org/moretypes/21

Cái tên "closure" ám chỉ rằng các function này được truy cập đến một khu vùng kín mà các function khác không thể động tới. Bởi vậy từ closure - đóng kín được sử dụng ở đây. Closure đôi khi còn được gọi là "function object".

==========
English version
EMACS LISP:
A closure is a function that also carries a record of the lexical environment that existed when the function was defined. When it is invoked, any lexical variable references within its definition use the retained lexical environment. In all other respects, closures behave much like ordinary functions; in particular, they can be called in the same way as ordinary functions.

Javascript:
Closures are functions that refer to independent (free) variables.
In other words, the function defined in the closure 'remembers' the environment in which it was created.

Swift:
Closures are self-contained blocks of functionality that can be passed around and used in your code

Go :
Go functions may be closures. A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables; in this sense the function is "bound" to the variables.

Scheme:
A closure is an abstraction in a functional programming language (e.g. Scheme) that represents a function and the scope in which it was created (lexical environment). This abstraction is also referred to as a function object.

Ruby: http://www.skorks.com/2010/05/closures-a-simple-explanation-using-ruby/
Javascript: http://www.jibbering.com/faq/notes/closures/
http://xahlee.info/UnixResource_dir/writ/closure.html
http://stackoverflow.com/questions/36636/what-is-a-closure
http://stackoverflow.com/questions/18502095/python-closure-vs-javascript-closure#18503395