Block quá quan trọng trong Ruby, khó tưởng tượng ngôn ngữ thiếu nó. Nhưng lambda? Ai yêu lambda? Bạn có thể đi nhiều năm không dùng. Chúng gần như di tích từ thời xa xưa.
...Nhưng không hẳn vậy. Lambda có thủ thuật thú vị khi khám phá kỹ.
Bài này bắt đầu từ cơ bản dùng lambda, rồi đến nâng cao. Nếu bạn dùng lambda hàng ngày và biết hết, cứ cuộn xuống.
Điều chính nhớ về Lambda: chúng hành xử như function. Block và Proc có ích. Nhưng không cái nào behave 100% như function thật. Lambda thì có. Xem danh sách:
Lambda ép buộc số lượng đối số đúng
Khác với Proc, lambda ép buộc số lượng đối số đúng.
Lambda hỗ trợ đối số mặc định
Ví dụ dưới tạo lambda function với đối số mặc định "hello world":
Lambda hỗ trợ đối số mặc định.
Từ khóa `return` hoạt động đúng như mong đợi
Có vẻ nhỏ, nhưng nếu từng dùng `return` trong proc thì biết nó không "bình thường".
Ví dụ dưới minh họa. Định nghĩa method `something` gọi `Proc`. `Proc` có `return`. Nhưng `return` đó tricky: thay vì return từ proc, nó return từ method `something`.
Khi làm tương tự với `lambda`, `return` chỉ return từ lambda. Giống function bình thường.
Khi dùng `return` trong lambda, nó return từ lambda.
Lambda là closure
Trích một bài Stack Overflow hay:
Cách đơn giản nhất hiểu closure: một function có thể lưu như biến ("first-class function"), với khả năng đặc biệt truy cập biến local trong scope nó được tạo.
Truy cập biến local trong scope tạo lambda nghĩa là gì? Xem ví dụ. Tạo biến local `marco`. Dùng trong lambda. Thay đổi giá trị biến, lambda thấy giá trị mới.
Ruby lambda là closure.
Lambda là "những con cam chameleon"
Một điều kỳ lạ về lambda: nhiều cách gọi khác nhau. Ví dụ dưới 보여 3 cách gọi lambda, tất cả tương đương.
Có ít nhất 3 cách gọi lambda trong Ruby.
Có vẻ hơi lạ. Cú pháp `l.(arg)` vẫn khiến tôi bối rối. Nhưng `l[arg]` thú vị: nghĩa là lambda có thể dùng ở nơi thường dùng array/hash.
Dùng lambda như Hash và Array tính toán
Giả sử test suite cần tạo fake Person records. Đơn giản: tạo FakePerson mới, truyền first/last name.
Nhưng muốn "fuzz test" bằng first/last name khác mỗi lần chạy test?
Cách một: truyền lambda function thay vì hash. Ví dụ dùng lambda sinh tên fake qua gem Faker tuyệt vời.
Ở đây, lambda giả vờ là hash.
Lambda có currying built-in
Currying là kỹ thuật cool dùng nhiều trong functional programming. Cho phép tạo function mới từ function có sẵn. Dễ hiểu qua thực hành.
Code dưới: lambda cộng hai số, tên `add`. Dùng currying tạo function chuyên biệt `increment` — chỉ cộng 1 vào số cho trước.
Bạn có thể curry bất kỳ proc nào trong Ruby.
Lambda là loại Proc đặc biệt
Bạn nhận ra trong các ví dụ, khi định nghĩa lambda, nhận về Proc. Vì Ruby implement lambda như một loại Proc. Vì vậy nhiều điều trong bài có thể làm với Proc cũng như lambda.
Stabby Lambda
Bài này dùng từ khóa `lambda` cho rõ ràng. Nhưng có cú pháp ngắn gọn hơn từ Ruby 1.9 gọi là "stabby lambda". Cách hoạt động:
Cú pháp stabby lambda của Ruby được giới thiệu từ phiên bản 1.9.