🔥
[Feature #21160] next の別名を追加する提案
[Feature #21160] Local return from proc
- 次のような DSL ライクな
fulfills_promise
なメソッドのブロック内から抜けるときにnext
を使うことがある
class Example
def self.fulfills_promise(promise_name, &block)
@@promise_callbacks ||= {}
@@promise_callbacks[promise_name] = block
end
def self.fulfill_promise(promise_name, data)
puts "Fulfilling promise: #{promise_name}"
callback = @@promise_callbacks[promise_name]
if callback.call(data)
puts 'Complete!'
else
puts 'Failed!'
end
end
fulfills_promise :generate_large_image do |image_data|
# 特定の条件の場合はなにもせずに処理を終わらせる
next false if image_data.nil?
puts 'Saving image..'
# etc.
true
end
end
Example.fulfill_promise(:generate_large_image, 'image data')
# => Complete!
Example.fulfill_promise(:generate_large_image, nil)
# => Failed!
- この
next
がわかりづらいので別の名前でエイリアスしたいという提案- チケットだと
pass
やcontinua
が提示されている
- チケットだと
- これなんですが
next
の変わりにbreak
を使うことがコメントされていますね - ただし、上記のコードの
next
をそのままbreak
に変えた場合にはLocalJumpError
が発生します
fulfills_promise :generate_large_image do |image_data|
# error: 'block in <class:Example>': break from proc-closure (LocalJumpError)
break false if image_data.nil?
puts 'Saving image..'
# etc.
true
end
- これの解決策として呼び出し元で
rescue LocalJumpError
することでbreak
やreturn
に対応できるみたいですね
class Example
def self.fulfills_promise(promise_name, &block)
@@promise_callbacks ||= {}
@@promise_callbacks[promise_name] = block
end
def self.fulfill_promise(promise_name, data)
puts "Fulfilling promise: #{promise_name}"
callback = @@promise_callbacks[promise_name]
begin
complete = callback.call(data)
rescue LocalJumpError => e
complete = e.exit_value
end
if complete
puts 'Complete!'
else
puts 'Failed!'
end
end
fulfills_promise :generate_large_image do |image_data|
# 特定の条件の場合はなにもせずに処理を終わらせる
break false if image_data.nil?
puts 'Saving image..'
# etc.
true
end
end
Example.fulfill_promise(:generate_large_image, 'image data')
# => Complete!
Example.fulfill_promise(:generate_large_image, nil)
# => Failed!
- この発想はなかった
- これだと
return
にも対応できるみたいですね - こういうのってあんまり書いたことないけど Rails とかでも多用されてたりするんですかね?
Discussion