在Ruby中捕获由于圆括号/大括号不匹配而导致的异常



以下是使用Ruby评估Excel公式的代码。此处仅显示SUM功能。我用两种语言RubyPython实现了这个功能

Python 3.10.0

def SUM(a,b):
return a+b
for i in range(int(input())):
s=input()
if s[0]!="=":
print("INVALID")
else:
try:
print(eval(s.replace('=','')))
except:
print("INVALID")

Ruby 3.0.2

def SUM a,b
a+b
end
gets
puts $<.map{
if !_1[/^=/]
:INVALID
else
eval(_1.tr(?=,'')) rescue :INVALID
end
}

考虑以下输入

输入1

4
=SUM(8, 99)
=SUM(343, -b1)
=SUM(-8,  -99)
=SUM(101 , -25) + 6

输入2

3
SUM(4, 1)
=SUM(5, 1
=SuM(2, 1)

对于Input 1,Ruby和Python代码都可以完美地工作。它们都捕捉到未定义的错误b1,因此进入exceptrescue

但对于输入2,只有Python代码可以完美地工作,而Ruby未能捕捉到丢失的错误)(第3行)。它不进入rescue。我也试过使用beginresuce。但什么都没有。如何挽救Ruby中的此类错误?

默认情况下,rubyrescue中的

只拯救StandardError的子类。这适用于大多数情况,因为您想要拯救的大多数东西都是该类的后代(NoMethodErrorRuntimeErrorArgumentError等),而您不想要拯救的大部分东西(NoMemoryErrorSyntaxErrorSystemExit等)则不是。

在您的案例中,eval("SUM(5, 1")缺少一个括号。这是一个语法错误,ruby引发SyntaxError。您的rescue正在查找StandardError,而SyntaxError不是。

您可以挽救所有标准错误+语法错误或挽救所有Exception秒,但请注意,如果您挽救了所有Exception秒,那么您的程序可能很难退出。

ctrl+cInterrupt,它是Exception的一个子类,可以被拯救。

进程上的kill是一个SignalException,它是Exception的子类,可以被挽救。

begin
eval(_1.tr(?=,''))
rescue StandardError, SyntaxError
:INVALID
end

begin
eval(_1.tr(?=,''))
rescue Exception # I strongly advise against this
:INVALID
end