Đó là không có thể chuyển đổi một proc thành lambda mà không gặp sự cố. Câu trả lời của Mark Rushakoff không bảo toàn giá trị của self
trong khối, vì self
trở thành Object.new
. Câu trả lời của Pawel Tomulik không thể làm việc với Ruby 2.1, bởi vì define_singleton_method
hiện trả về một Biểu tượng, vì vậy to_lambda2
trả về :_.to_proc
.
câu trả lời của tôi là cũng sai:
def convert_to_lambda &block
obj = block.binding.eval('self')
Module.new.module_exec do
define_method(:_, &block)
instance_method(:_).bind(obj).to_proc
end
end
Nó bảo tồn giá trị của self
trong khối:
p = 42.instance_exec { proc { self }}
puts p.lambda? # false
puts p.call # 42
q = convert_to_lambda &p
puts q.lambda? # true
puts q.call # 42
Nhưng nó không thành công với instance_exec
:
puts 66.instance_exec &p # 66
puts 66.instance_exec &q # 42, should be 66
tôi phải sử dụng block.binding.eval('self')
để tìm đúng đối tượng. Tôi đặt phương thức của mình vào một mô-đun ẩn danh, vì vậy nó không bao giờ gây ô nhiễm bất kỳ lớp nào. Sau đó, tôi ràng buộc phương pháp của tôi với đối tượng chính xác. Điều này làm việc mặc dù các đối tượng không bao giờ bao gồm các mô-đun! Phương pháp ràng buộc tạo ra một lambda.
66.instance_exec &q
không thành công vì q
bí mật là phương thức được liên kết với 42
và instance_exec
không thể khởi động lại phương thức. Người ta có thể sửa lỗi này bằng cách mở rộng q
để hiển thị phương thức không gắn kết và xác định lại instance_exec
để liên kết phương thức không gắn kết với một đối tượng khác. Mặc dù vậy, module_exec
và class_exec
vẫn không thành công.
class Array
$p = proc { def greet; puts "Hi!"; end }
end
$q = convert_to_lambda &$p
Hash.class_exec &$q
{}.greet # undefined method `greet' for {}:Hash (NoMethodError)
Vấn đề là Hash.class_exec &$q
định nghĩa Array#greet
và không Hash#greet
. (Mặc dù $q
là bí mật một phương thức của một mô-đun ẩn danh, nó vẫn định nghĩa các phương thức trong Array
, không phải trong mô-đun ẩn danh.) Với proc ban đầu, Hash.class_exec &$p
sẽ xác định Hash#greet
. Tôi kết luận rằng convert_to_lambda
là sai vì nó không hoạt động với class_exec
.
Cảm ơn! Rất hữu ích :) Thực tế là define_method cuối cùng tạo ra một lambda là những gì nhắc nhở sự nhầm lẫn của tôi. –
Thời gian câu hỏi thú vị: làm thế nào để bạn làm điều này trong jruby? – Schneems
Trả lời cho câu hỏi thú vị của tôi: http://stackoverflow.com/questions/13239338/convert-bloc-to-lambda-in-jruby – Schneems