Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby “红宝石”;“错误时继续下一步”;功能_Ruby - Fatal编程技术网

Ruby “红宝石”;“错误时继续下一步”;功能

Ruby “红宝石”;“错误时继续下一步”;功能,ruby,Ruby,有没有办法在ruby中执行旧的“错误恢复下一步”例程 我已经从其他地方动态填充了一个值数组(准确地说是从MQTT主题中读取的),然后我想对它们进行一系列数值计算并发布结果。值应为数字,但可能缺失或非数字 目前,我的代码看起来像 values=[] //values get loaded here begin Publish('topic1',value[0]*10+value[1]) rescue TypeError,NoMethodError,ZeroDivisionError e

有没有办法在ruby中执行旧的“错误恢复下一步”例程

我已经从其他地方动态填充了一个值数组(准确地说是从MQTT主题中读取的),然后我想对它们进行一系列数值计算并发布结果。值应为数字,但可能缺失或非数字

目前,我的代码看起来像

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来说,这是一个新的概念。我仍然在思考代码块,并向提出相同解决方案的其他人致歉:您的输入同样重要,但我只能选择一个“接受的答案”。我已经学会了