function outerFunction(input) {
var closureVar = "I'm here with ";
function innerFunction() {
return closureVar + input;
}
return innerFunction();
}
console.log(outerFunction('outer input')); // I'm here with outer input
讓我們先來重新寫你的ECMAScript使用函數表達式:
const outerFunction = function (input) {
const closureVar = "I'm here with ";
const innerFunction = function() {
return closureVar + input;
}
return innerFunction();
}
console.log(outerFunction('outer input')); // I'm here with outer input
現在讓我們重新編寫成多模式RN風格:
const outerFunction = input => {
const closureVar = "I'm here with ";
const innerFunction =() => closureVar + input;
return innerFunction();
};
console.log(outerFunction('outer input')); // I'm here with outer input
現在,它實際上是相當簡單的這個翻譯到Ruby:
outer_function = -> input {
closure_var = "I'm here with "
inner_function = -> { closure_var + input }
inner_function.()
}
puts outer_function.('outer input') # I'm here with outer input
正如你所看到的,翻譯其實是非常簡單和語義類似。但是,它不是非常習慣的Ruby。一般而言,對於封裝狀態,對象和方法比封閉更受歡迎,但有時,封閉是有用的和使用的。
更地道的風格可能是這樣的:
def outer_method(input)
closure_var = "I'm here with "
inner_function = -> { closure_var + input }
inner_function.()
end
puts outer_method('outer input') # I'm here with outer input
但對於這樣一個小玩具例如,它很難說,很難證明紅寶石會是什麼樣習慣等。
如果您對這樣的東西感興趣,您可能需要查看toy project of mine,在那裏我將展示如何使用各種語言(包括Clojure和其他各種Lisp,Smalltalk和一些它的後代,ECMAScript和CoffeeScript,Ruby,Python,PHP,Perl等。請注意,代碼在大多數語言中看起來非常相似,但是請注意代碼在幾乎所有語言中都非常不習慣,除了Scheme和Clojure的。就我所知,它甚至不是慣用的CommonLisp。
你在你的問題下半年發佈的Ruby代碼是完全無關的任何代碼或在你的問題上半年的概念:沒有關閉,沒有詞法作用域的問題,並有不需要使用它們。
事實上,您發佈的第一個片段只是工作作爲-是:
def outer_function
list = [ 1, 2, 3 ]
list.each { |item| print item }
end
outer_function
# 123
第二隻是有一個小問題:
def outer_function
list = Proc.new { return [ 1, 2, 3 ] }
# The call to `each` is dead code since the call to `list.call` will already return
list.call.each { |item| another_function item }
end
# This method never gets called
def another_function item
puts item
end
outer_function
# => [1, 2, 3]
return
被用於從返回一個值方法。那麼,return
從哪個方法返回?那麼,它從outer_function
返回,因爲那是唯一的方法! list
是一個Proc
,而不是一種方法。要從Proc
回報,你使用next
關鍵字來代替:
def outer_function
list = Proc.new { next [ 1, 2, 3 ] }
list.call.each { |item| another_function item }
end
def another_function item
puts item
end
outer_function
# 1
# 2
# 3
或者,你可以乾脆離開了next
,自上次表達的化合物表達內評估(塊,一個方法,一個類,無論)是它的返回值反正:
def outer_function
list = Proc.new { [ 1, 2, 3 ] }
list.call.each { |item| another_function item }
end
def another_function item
puts item
end
outer_function
# 1
# 2
# 3
或者,你可以用一個lambda更換Proc
(這實際上也是一個Proc
但略有不同的語義):
def outer_function
list = -> { return [ 1, 2, 3 ] }
list.call.each { |item| another_function item }
end
def another_function item
puts item
end
outer_function
# 1
# 2
# 3
有Proc
S(由Proc.new
或Kernel#proc
創建)和lambda表達式(由Kernel#lambda
創建或stabby拉姆達字面-> (params) { code }
)之間的兩個語義差異:在從詞法封閉方法Proc
返回return
(就像在一個塊中)而lambda中的return
從lambda本身返回(就像在方法中一樣),並且Proc
的參數綁定語義與塊的參數綁定語義相同,而lambda表達式的參數綁定語義與方法的相同。
回顧:有兩個區別,return
和參數綁定。在這兩種情況下,Proc
的行爲就像一個塊,lambda表現得像一個方法。助記符:Proc
帶有「block」和「lambda」和「method」的押韻都是希臘字母。
你是什麼意思由*#失敗,因爲列表中有環路*的第二次迭代一個未定義的方法? – Atri
對不起,我遺漏了我的代碼不完整。我實際上正在調用循環中的另一個函數。所以我相信一旦它調用該函數,它會將列表重置爲零。我用了一個開始和救援塊,這對我來說似乎正在發生。 – user3162553
然後顯示實際的代碼。 – Atri