短:
Ruby中有没有办法干掉这个:
def entry_point_one
begin
do_something
rescue MySyntaxErrorOne, MySyntaxErrorTwo, MySyntaxErrorEtc => syn_err
raise syn_err.exception(syn_err.message)
end
end
def entry_point_two
begin
do_something_else
rescue MySyntaxErrorOne, MySyntaxErrorTwo, MySyntaxErrorEtc => syn_err
raise syn_err.exception(syn_err.message)
end
end
长:
我正在建立一名翻译。可以使用不同的入口点调用此解释器。如果我为这个解释器提供一个'脏'字符串,我希望它会引发错误。但是,如果我没有被do_something直接或间接调用的每个方法的整个回溯追踪,那将是很好的,特别是因为解释器使用了递归。
正如您在上面的代码段中所看到的,我已经知道了一种重新引发错误并从而删除回溯的方法。我想要做的是删除上面示例中的重复。我到目前为止最接近的是:
def entry_point_one
re_raise_known_exceptions {do_something}
end
def entry_point_two
re_raise_known_exceptions {do_something_else}
end
def re_raise_known_exceptions
yield
rescue MySyntaxErrorOne, MySyntaxErrorTwo, MySyntaxErrorEtc => syn_err
raise syn_err.exception(syn_err.message)
end
但这会使方法重新加注 - 已知 - 异常显示在后面的跟踪中。
编辑:我想我想要的就像C预处理宏
答案 0 :(得分:3)
您可以在阵列上使用splat。
直接来自IRB:
COMMON_ERRORS = [ArgumentError, RuntimeError] # add your own
def f
yield
rescue *COMMON_ERRORS => err
puts "Got an error of type #{err.class}"
end
f{ raise ArgumentError.new }
Got an error of type ArgumentError
f{ raise 'abc' }
Got an error of type RuntimeError
答案 1 :(得分:2)
在考虑它的同时,我想出了这个:
interpreter_block {do_something}
def interpreter_block
yield
rescue ExceptionOne, ExceptionTwo, ExceptionEtc => exc
raise exc.exception(exc.message)
end
虽然它仍然不是我想要的安静,但至少现在后面跟踪中的额外条目变得更好看了。
答案 2 :(得分:1)
它可能有点恶,但我认为你可以简单地从回溯中删除该行; - )
COMMON_ERRORS = [ArgumentError, RuntimeError]
def interpreter_block
yield
rescue *COMMON_ERRORS => err
err.backtrace.delete_if{ |line| line=~/interpreter_block/ }
raise err
end
我不确定这是个好主意。之后调试你的口译员会有很多乐趣; - )
附注:Treetop可能是你感兴趣的。
答案 3 :(得分:1)
这是一种触动的hackish,但就清理回溯而言,这样的事情很有效:
class Interpreter
def method1
error_catcher{ puts 1 / 0 }
end
def error_catcher
yield
rescue => err
err.set_backtrace(err.backtrace - err.backtrace[1..2])
raise err
end
end
主要技巧是这一行err.set_backtrace(err.backtrace - err.backtrace[1..2])
。没有它,我们得到以下(来自IRB):
ZeroDivisionError: divided by 0
from (irb):43:in `/'
from (irb):43:in `block in method1'
from (irb):47:in `error_catcher'
from (irb):43:in `method1'
from (irb):54
from /Users/peterwagenet/.ruby_versions/ruby-1.9.1-p129/bin/irb:12:in `<main>'
我们不想要的是第二和第三行。所以我们删除它们,结果是:
ZeroDivisionError: divided by 0
from (irb):73:in `/'
from (irb):73:in `method1'
from (irb):84
from /Users/peterwagenet/.ruby_versions/ruby-1.9.1-p129/bin/irb:12:in `<main>'
答案 4 :(得分:0)
如果您拥有异常中所需的所有信息,并且根本不需要回溯,则可以定义自己的错误并提出错误,而不是重新加载现有异常。这将给它一个新的回溯。 (当然,大概你的示例代码是不完整的,救援块中还会发生其他处理 - 否则你最好的办法就是让错误自然地冒出来。)
class MyError < StandardError; end
def interpreter_block
yield
rescue ExceptionOne, ExceptionTwo, ExceptionEtc => exc
raise MyError
end