Tôi đã tự hỏi làm cách nào để truyền một khối tới một phương thức sẽ thực hiện phương thức return
trên yield
.Tìm hiểu về việc quay trở lại từ procs trong Ruby
Các aproach ngây thơ không hoạt động:
def run(&block)
block.call
end
run { return :foo } # => LocalJumpError
Wrapping trong proc khác có tác dụng tương tự:
def run(&block)
proc { block.call }.call
end
run { return :bar } # => LocalJumpError
Vì vậy, tôi nghĩ rằng tuyên bố return
được ràng buộc với receiver
của dòng điện binding
. Tuy nhiên, cố gắng nó ra với instance_eval
chứng minh tôi sai:
class ProcTest
def run(&block)
puts "run: #{[binding.local_variables, binding.receiver]}"
instance_eval(&block)
end
end
pt = ProcTest.new
binding_inspector = proc { puts "proc: #{[binding.local_variables, binding.receiver]}" }
puts "main: #{[binding.local_variables, binding.receiver]}"
# => main: [[:pt, :binding_inspector], main]
binding_inspector.call
# => proc: [[:pt, :binding_inspector], main]
pt.run(&binding_inspector)
# => run: [[:block], #<ProcTest:0x007f4987b06508>]
# => proc: [[:pt, :binding_inspector], #<ProcTest:0x007f4987b06508>]
pt.run { return :baz }
# => run: [[:block], #<ProcTest:0x007f4987b06508>]
# => LocalJumpError
Vì vậy, câu hỏi là:
- Làm thế nào điều này có thể được thực hiện?
- Ngữ cảnh trả về được gắn với câu hỏi
return
. Kết nối này có thể truy cập được qua API của ngôn ngữ không? - Việc này có được thực hiện theo cách như vậy không? Nếu đúng thì tại sao? Nếu không - các chướng ngại vật để sửa chữa nó là gì?
Bạn không trả lời một một câu hỏi. Điểm đầu tiên - tôi biết rằng tôi nhận được ngoại lệ bởi vì tôi đang cố gắng 'return' từ phạm vi * main * và' return' được gắn với phạm vi đã định nghĩa nó. Về phần thứ hai - tôi biết * lambdas * có ngữ nghĩa 'return' khác với procs * thông thường *, câu hỏi không phải về chúng. Tôi cũng biết về 'throw' - 'catch', câu hỏi là về sự hiểu biết' return'. Nó giống như hỏi * tại sao là cỏ xanh? * Và nhận được một câu trả lời * nhìn cỏ này, bạn có thể thấy rằng đó là màu xanh lá cây, nước không phải là màu xanh lá cây và bạn có thể vẽ cỏ giả trong không màu xanh lá cây *. – ndn
Không có cơ sở nào để Ruby truyền một khối tới một phương thức có thể trở về từ bên trong khối, trong khi phương thức này được chuyển tới vì hành vi trả về như vậy sẽ loại trừ lẫn nhau với các hành vi trả về hiện có. Tôi không biết * tại sao * nó được thiết kế theo cách đó, nhưng "tại sao Ruby không có cái này" được trả lời, và do đó Q1 được trả lời (bạn không thể), Q3 là không thích hợp (nó không phải là lỗi để được cố định, đó là một lựa chọn có chủ ý của các lựa chọn thay thế lẫn nhau), Q2 sẽ yêu cầu nhận được vào phân tích cú pháp và mã VM để trả lời, nhưng câu trả lời có lẽ là "ngữ cảnh không được phơi bày". –
Bạn có ý nghĩa gì bởi * vì hành vi trả lại như vậy sẽ loại trừ lẫn nhau với các hành vi trả lại hiện tại * và * lựa chọn có chủ ý các lựa chọn thay thế lẫn nhau *? Hành vi mong muốn nào sẽ bị hỏng nếu nó được thực hiện để trả về từ phương thức gọi. Không phải là thực thi proc thêm vào ngăn xếp khi nó được gọi là? * tại sao Ruby không có điều này * ngụ ý rằng đây là một tính năng bổ sung, mà không phải là. – ndn