我正在尝试使用Ruby方法做一些不寻常的事情。我想让 terminate 在下面的代码中表现得像一个显式的return语句:
def terminate(data)
data.upcase
#I want to put a command somewhere in this scope
end
def other_method
data = "cow"
terminate data
data = "fox"
end
other_method
#Desired response
#> "COW"
#Actual response in everything that we try
#> "fox"
我希望other_method返回“COW”。具体来说,通过使'terminate'作为显式返回语句起作用。有什么我可以投掷/加注会做到这一点?或者其他一些hacky方式我可以强迫这种行为?
目前,在我们的代码中,我们总是使用(在大型代码库中经常更改它的很多很多实例):
return foo! param1, param2
return foo2! param1, param2
return foo3! param1, param2
我们想用以下内容替换它:
foo! param1, param2
foo1! param1, param2
foo2! param1, param2
foo没有别的办法!在我们的代码库中按设计使用。它基本上是语法糖。
答案 0 :(得分:5)
在Ruby中,除非在方法的其他地方使用显式return
语句,否则在方法中执行的最后一行是返回的内容。也许复杂性在你更简单的例子中迷失了,但是:你能将terminate
的结果存储在变量中并返回吗?
def other_method
data = "cow"
result = terminate data
data = "fox"
result
end
答案 1 :(得分:3)
在Ruby中,除非你在你的其他地方使用显式的return语句 方法,你的方法的最后一行是返回的。
这是不正确的。
我们尝试的所有内容的实际响应=> “狐狸”
没有显式return语句的ruby方法返回执行的最后一个语句的结果。这是在您的方法中执行的最后一个语句:
data = "fox"
并且赋值语句的“结果”是右侧,因此您的方法返回'fox'。如果该行总是在您的方法中执行的最后一行,您的方法将始终返回'fox'。
对评论的回应:
你可以这样做(但我看不出它会对你有什么帮助):
def other_method
data = "cow"
func = Proc.new {|data| return data.upcase}
func[data]
data = "fox"
end
puts other_method
--output:--
COW
但你不能这样做:
def other_method(func)
data = "cow"
func[data]
data = "fox"
end
f = Proc.new { |data| return data.upcase }
other_method(f)
--output:--
unexpected return (LocalJumpError)
...
Is there something I can throw / raise that will do this?
是的,你可以这样做:
class MyTerminateMethodError < Exception
end
def terminate(d)
raise MyTerminateMethodError, d.upcase
end
def other_method
data = "cow"
terminate data
data = "fox"
rescue MyTerminateMethodError => result
result #This is the last statement to execute, so result is returned
end
puts other_method
--output:--
COW
但事实是,将数据传递给terminate()方法没有任何好处,因为你可以这样做:
class MyTerminateMethodError < Exception
end
def terminate
raise MyTerminateMethodError
end
def other_method
data = "cow"
terminate
data = "fox"
rescue MyTerminateMethodError
data.upcase
end
puts other_method
相当于:
class MyTerminateMethodError < Exception
end
def other_method
data = "cow"
raise MyTerminateMethodError
data = "fox"
rescue MyTerminateMethodError
data.upcase
end
puts other_method
可以更有效地编写:
def other_method
data = "cow"
return data.upcase
data = "fox"
end
好的,但您希望将不同的行为应用于数据 - 而不仅仅是upcase()?一块怎么样?
def other_method
data = "cow"
if block_given?
return (yield data)
end
data = "fox"
end
result = other_method { |x| x.capitalize }
puts result =>Cow
如果您无法更改other_method(),那么您可以这样做:
class MyTerminateMethodError < Exception
end
def terminate(d)
raise MyTerminateMethodError, d.upcase
end
def other_method
data = "cow"
terminate data
data = "fox"
end
result = begin
other_method
rescue MyTerminateMethodError => str
end
puts result #=>COW
答案 2 :(得分:2)
throw / catch会这样做。
在调用Kernel#catch:
时,将您方法的内容包裹起来def something
catch :return do
foo! 123, 456
end
end
#foo!
来电Kernel#throw:
def foo!(*args)
throw :return, args
end
调用#throw时,会导致异常被#catch语句捕获。然后#catch语句的结果是赋予#throw语句的值。因此:
p something # [123, 456]
如果未调用#throw,则#catch的结果是其块中执行的最后一个语句的结果。