12/08/2018, 14:51

Funtion tiến hoá trở thành Closure và cái kết bất ngờ!

Đầu tiên chúng ta thử tìm hiểu quá trình biến đổi 1 function trở thành 1 closure như thế nào func greater(first: Double, last: Double) -> Bool { return first > last } ta muốn biến đổi function này trở thành 1 closure. var greaterClosure: (Double,Double) -> Bool ...

Đầu tiên chúng ta thử tìm hiểu quá trình biến đổi 1 function trở thành 1 closure như thế nào

    func greater(first: Double, last: Double) -> Bool {
        return first > last 
    }

ta muốn biến đổi function này trở thành 1 closure.

    var greaterClosure: (Double,Double) -> Bool 

Trước hết ta cứ để copy cả function vào cùng 1 dòng với closure

    var greaterClosure: (Double, Double) -> Bool =  func greater(first: Double, last: Double) -> Bool {
        return first > last 
    }

greateClosure ở đây đã là tên của closure này rồi nên việc đặt thêm 1 cái tên là greater không đem lại thêm giá trị gì. Vì vậy chúng ta sẽ remove những thành phần vô nghĩa này đi

     var greaterClosure: (Double, Double) -> Bool = (first: Double, last: Double) -> Bool {
        return first > last 
    }        

Để có thể hiểu được function tương đương với 1 giá trị được gán vào, người ta nghĩ ra một cách đóng gói các nội dung lại vào trong các gói đóng {} - di chuyển { ra ngoài cùng. Nhưng làm thế nào để phân định được đâu là header của closure và đâu là body của closure -> Lúc này một chữ in được thêm vào thay vào vị trí dấu mở ngoặc đã dời đi

     var greaterClosure: (Double, Double) -> Bool = {(first: Double, last: Double) -> Bool  in
        return first > last 
    }        

Rõ ràng là greaterClosure nó đã có định nghĩa của nó là loại nhận 2 giá trị đầu vào là (Double, Double) và trả ra giá trị Bool, nên có vẻ việc viết loại của prameter trong phần header của closure là không cần thiết

     var greaterClosure: (Double, Double) -> Bool = {(first, last)  in
        return first > last 
    }        

Hai tham số truyền vào thì thằng nào đặt trước là ở trước, thằng nào đặt sau là ở sau thì cớ gì còn phải cho thêm cái tên first và last vào làm gì nhỉ - chỉ cần chỉ định vị trí số 1 là $0, vị trí số 2 là $$ là ok rồi mà?

     var greaterClosure: (Double, Double) -> Bool = {($0, $1)  in
        return $0 > $1
    }        

Nhưng mà thế thì cần gì phải khai báo header của closure làm gì nhỉ? đã có $0, và $$ để biểu thị các tham số đầu vào rồi mà nhỉ? thế thì cũng có cần chữ in ở đây nữa ko nhỉ? Thôi xoá thôi

     var greaterClosure: (Double, Double) -> Bool = {
        return $0 > $1
    }   

Cả closure có giá trị 1 giá trị trả về, ko cần nói return người ta có hiểu là gì ko mà phải nói làm gì cho mất thời gian? Xoá thôi!

     var greaterClosure: (Double, Double) -> Bool = { $0 > $1}   

Trong một hàm có hai đầu vào, thường thì thằng đầu tiên ở bên trái, thằng thứ 2 ở bên phải. Có mỗi hai thằng thì với một công thức 2 biến số thì cần gì phải phân biệt $0, $$ làm gì nữa? Xoá thôi!

     var greaterClosure: (Double, Double) -> Bool = {>}   

That great! Thật ra closure và function đều có những vai trò khác nhau, closure là dạng ngắn gọn xúc tích của function nhưng nó không thay thế hay xoá bỏ việc sử dụng function. Vì vậy, function là function, closuer vẫn là closure, và function có thể biến đổi, rút gọn lại về dạng Closure bằng các cách như trên.

các bạn thử xem các closure sau có ý nghĩa như thế nào nhé

    var greaterSize : (CGSize, CGSize) -> Bool = {$0.awidth > $1.awidth && $0.height > $1.height}
    var greaterPoint : (CGPoint, CGPoint) -> Bool = {$0.x > $1.x && $0.y > $1.y}
    var completeClosure : (String) -> Void = {printn($0)}
0