Ruby “红宝石”;“错误时继续下一步”;功能
有没有办法在ruby中执行旧的“错误恢复下一步”例程 我已经从其他地方动态填充了一个值数组(准确地说是从MQTT主题中读取的),然后我想对它们进行一系列数值计算并发布结果。值应为数字,但可能缺失或非数字 目前,我的代码看起来像Ruby “红宝石”;“错误时继续下一步”;功能,ruby,Ruby,有没有办法在ruby中执行旧的“错误恢复下一步”例程 我已经从其他地方动态填充了一个值数组(准确地说是从MQTT主题中读取的),然后我想对它们进行一系列数值计算并发布结果。值应为数字,但可能缺失或非数字 目前,我的代码看起来像 values=[] //values get loaded here begin Publish('topic1',value[0]*10+value[1]) rescue TypeError,NoMethodError,ZeroDivisionError e
values=[]
//values get loaded here
begin
Publish('topic1',value[0]*10+value[1])
rescue TypeError,NoMethodError,ZeroDivisionError
end
begin
Publish('topic2',value[3]/value[4])
rescue TypeError,NoMethodError,ZeroDivisionError
end
//etc etc
def safe_Publish(topic,value)
return if value.nil?
Publish(topic,value)
end
如果由于任何原因计算失败,程序应跳过该步骤并继续
它是有效的,但肯定有比所有这些相同的开始更好的方法。营救积木?Ruby毕竟是“干的”
是否有办法重新编写上述内容,以便在仍然允许进行所有计算的情况下使用单个begin..rescue构造
已更新
这样做有多安全
values=[]
//values get loaded here
begin
Publish('topic1',value[0]*10+value[1])
rescue TypeError,NoMethodError,ZeroDivisionError
end
begin
Publish('topic2',value[3]/value[4])
rescue TypeError,NoMethodError,ZeroDivisionError
end
//etc etc
def safe_Publish(topic,value)
return if value.nil?
Publish(topic,value)
end
打电话给
安全发布('topic2',(值[3]/值[4]为零)
主要的问题是,上面的内容捕捉到了所有异常,而不仅仅是我预期的异常,这让我有点紧张。这展示了如何将一系列快速操作打包成一个循环,每个操作都由begin/rescue保护:
values = [1,2,3,0,4]
ops = [ ->{values[0]/values[1]}, ->{values[2]/values[3]} ]
ops.each do |op|
begin
puts "answer is #{op.call}"
rescue ZeroDivisionError
puts "cannot divide by zero"
end
end
但是,我更喜欢safe\u publish
方法,因为您可以对其进行单元测试,它将安全调用和处理错误的逻辑封装在一个地方:
def safe_publish(topic, &block)
begin
value = block.call
publish(topic, value)
rescue
# handle the error
end
end
然后你可以用如下代码调用它:
safe_publish 'topic0' do
value[0]*10+value[1]
end
这显示了如何将一系列快速操作打包成一个循环,每个操作都受到begin/rescue的保护:
values = [1,2,3,0,4]
ops = [ ->{values[0]/values[1]}, ->{values[2]/values[3]} ]
ops.each do |op|
begin
puts "answer is #{op.call}"
rescue ZeroDivisionError
puts "cannot divide by zero"
end
end
但是,我更喜欢safe\u publish
方法,因为您可以对其进行单元测试,它将安全调用和处理错误的逻辑封装在一个地方:
def safe_publish(topic, &block)
begin
value = block.call
publish(topic, value)
rescue
# handle the error
end
end
然后你可以用如下代码调用它:
safe_publish 'topic0' do
value[0]*10+value[1]
end
下一步继续出错时的
编码风格确实很危险,因为它使查找意外引入程序的新bug变得非常困难。相反,我会编写一个不同版本的publish,它不会抛出这些异常:
def try_publish(topic_name)
begin
Publish('topic1',yield)
rescue TypeError,NoMethodError,ZeroDivisionError
# are you sure you don't want to do anything here? Even logging the errors
# somewhere could be useful.
end
end
然后,您可以通过以下方式调用此选项:
try_publish('topic1') { value[0]*10+value[1] }
如果表达式抛出TypeError、NoMethodError或ZeroDivisionError,它们将被捕获并忽略
现在,您原来的方法不需要任何救援
如果您真的希望在下一步恢复出错时执行
,您可以通过在内核中对raise
方法进行monkey补丁来实现,但是那将是一个可怕的想法。下一步错误恢复时的编码风格非常危险,因为它使得查找意外引入程序的新bug非常困难。相反,我会编写一个不同版本的publish,它不会抛出这些异常:
def try_publish(topic_name)
begin
Publish('topic1',yield)
rescue TypeError,NoMethodError,ZeroDivisionError
# are you sure you don't want to do anything here? Even logging the errors
# somewhere could be useful.
end
end
然后,您可以通过以下方式调用此选项:
try_publish('topic1') { value[0]*10+value[1] }
如果表达式抛出TypeError、NoMethodError或ZeroDivisionError,它们将被捕获并忽略
现在,您原来的方法不需要任何救援
如果你真的想在下一次出错时恢复,你可以通过在内核中对raise
方法进行猴子补丁来实现,但那将是一个可怕的想法。如果你仔细考虑一下你正在做什么,以及为什么要在下一次出错时恢复,我认为您将看到,实际上并不需要抑制所有异常。正如其他海报所指出的,这将使发现和修复bug变得困难
你的问题是,你有一大堆从互联网上刮下来的数字,想对它们进行一些计算,但有些可能是无效的或丢失的。对于无效/缺失的数字,您希望跳过任何使用这些数字的计算
一些可能的解决方案:
预筛选数据并删除任何无效数字
把你想做的每一个计算都放到自己的方法中。在方法定义上放置一个救援异常
为数字类定义“安全”包装,这些数字类在除法为零等情况下不会引发异常。使用这些包装进行计算
“包装器”可能看起来像这样(不要期望完整的、经过测试的代码;这只是给您一个想法):
然后像这样使用它:
numbers = scraped_from_net.map { |n| SafeNumeric.new(n) }
# now you can do arithmetic on "numbers" at will
如果您更仔细地考虑一下您正在做什么,以及为什么要在下一步的错误恢复中使用,
,我想您会发现,您实际上不需要抑制所有异常。正如其他海报所指出的,这将使发现和修复bug变得困难
你的问题是,你有一大堆从互联网上刮下来的数字,想对它们进行一些计算,但有些可能是无效的或丢失的。对于无效/缺失的数字,您希望跳过任何使用这些数字的计算
一些可能的解决方案:
预筛选数据并删除任何无效数字
把你想做的每一个计算都放到自己的方法中。在方法定义上放置一个救援异常
为数字类定义“安全”包装,这些数字类在除法为零等情况下不会引发异常。使用这些包装进行计算
“包装器”可能看起来像这样(不要期望完整的、经过测试的代码;这只是给您一个想法):
然后像这样使用它:
numbers = scraped_from_net.map { |n| SafeNumeric.new(n) }
# now you can do arithmetic on "numbers" at will
你能澄清一下吗?如果您打算写“发布(主题名称、值)”并被称为“try\u Publish('topic1',value[0]*10+value[1]”那么,在调用该方法之前肯定会抛出数值异常?对不起,我的原始答案根本没有用处。我现在通过使用一个块来通过可能失败的计算来修复它。由于该块在内部begin/rescue部分执行,异常将被捕获。nanothief-看起来好多了。作为一个对于ruby来说,这是一个新的概念。我仍然在思考代码块,并向提出相同解决方案的其他人致歉:您的输入同样重要,但我只能选择一个“接受的答案”。我已经学会了