Ruby和Groovy是兩種看上去很相似的程式設計語言,但由于運作時機制的不同,導緻兩種程式設計語言在block中的return語句處理有很大差别,具體原因在于:
- Ruby在語言設計上很大程度上參考了Smalltalk。在Smalltalk程式設計語言中,block可以直接傳回到調用函數外層,這一語言特性稱為non-local return。Ruby也有此特性。
- Groovy的運作時是基于JVM的,在JVM規範中不存在non-local return這樣的特性,于是,在block中使用return語句的行為就和Ruby不同。
在下面這段Ruby代碼中,由于non-local return特性,bar函數裡的block中的return語句會導緻bar函數傳回:
def foo
[1,2,3].map{ |a| 2*a }
end
def bar
[1,2,3].map{ |a| return 2*a }
end
p foo #[2, 4, 6]
p bar #2
同樣的Groovy代碼,在block中使用return語句不會對運作結果産生影響, foo和bar這兩個函數的行為完全一樣:
def foo() {
[1, 2, 3].collect { it * 2 }
}
def bar() {
[1, 2, 3].collect { return it * 2 }
}
println(foo()) //[2, 4, 6]
println(bar()) //[2, 4, 6]
再看一個更真實的例子:
Ruby代碼實作的一個判重邏輯:
def in_list(l, e)
l.each do |x|
if x == e then
return true
end
end
return false
end
p in_list([1, 2], 1) #true
同樣寫法的Groovy代碼的運作結果是不對的:
def in_list(l, e) {
l.each {
if (it == e) {
return true
}
}
return false
}
println(in_list([1, 2], 1)) #false
必須改寫成:
def in_list(l, e) {
for (it in l) {
if (it == e) {
return true
}
}
return false
}
println(in_list([1, 2], 1)) #true
綜上,當同時使用這兩種程式設計程式設計語言編碼時必須加倍小心,特别要注意分辨帶return語句的block的不同行為,并在必要時加以改寫。