如何在 Ruby 中编写 IIFE?
How can I write an IIFE in Ruby?
在Javascript中,一个IIFE(立即调用的函数表达式,虽然可能还有其他缩写词的扩展)可以写成:
(function () {
var foo = 'bar'
console.log('hi!');
})();
其中变量声明foo
不会污染当前作用域。我怎样才能在 Ruby 文件中做同样的事情?
我想在受限范围内创建一些临时变量(带闭包),并使文件中的其他代码稍后无法访问它们。
defined?(foo)
# => nil
# This defines a lambda, i.e. a closure with its own variable scope, among other things
# and directly executes it
lambda {
foo = 'bar'
puts foo
}.()
defined?(foo)
# => nil
在这个例子中,我们首先检查变量foo
是否被定义,它没有。然后,我们创建一个新的lambda对象(在Ruby中是一种特殊的Proc。并直接执行它。
Proc 继承周围作用域的变量,因此所有已经定义的局部变量也可以在 proc 内部访问(和更改)。然而,仅在 proc 中定义的新变量在 proc 之外是不可见的。
这可以用最后的 defined?
语句来验证。
请注意,此技术不是很 ruby。相反,您应该旨在创建可以调用的实际方法。为了封装数据和行为,您还可以创建小的 类,即使是一次性使用也可以完全处理您的行为和所有必需的数据。
通常在 Ruby 中,您倾向于不传递匿名闭包(即 javascript 中的匿名函数或 Ruby 中的 procs/lambdas/blocks),而是使用完整对象。如果您经常在代码中使用上述技术,经验丰富的 ruby 开发人员会关注您。
好吧,你也可以这样做:写一个任意的 lambda 文字,然后立即调用它。
但有一个警告:Ruby 没有变量声明。因此,任何在块内使用也存在于块外的变量名都是指捕获的外部变量,而在 ECMAScript 中,如果您在函数内声明 var foo
,它将隐藏外部变量 foo
.
如果你想在 Ruby 中有相同的行为,你必须在块的参数列表中明确声明 foo
作为块局部变量:
-> (;foo) do
foo = 'bar'
puts 'hi!'
end.()
如果不这样做,块内的赋值将修改捕获的外部绑定。比较:
foo = 'foo'
-> do
foo = 'bar'
puts 'hi!'
end.()
foo
# => 'bar'
如您所见,外部绑定已修改。
foo = 'foo'
-> (;foo) do
foo = 'bar'
puts 'hi!'
end.()
foo
# => 'foo'
如您所见,只有第二个真正匹配 ECMAScript 版本:
"use strict";
const foo = 'foo';
(() => {
const foo = 'bar';
console.log('hi!');
})()
foo
// => 'foo'
在Javascript中,一个IIFE(立即调用的函数表达式,虽然可能还有其他缩写词的扩展)可以写成:
(function () {
var foo = 'bar'
console.log('hi!');
})();
其中变量声明foo
不会污染当前作用域。我怎样才能在 Ruby 文件中做同样的事情?
我想在受限范围内创建一些临时变量(带闭包),并使文件中的其他代码稍后无法访问它们。
defined?(foo)
# => nil
# This defines a lambda, i.e. a closure with its own variable scope, among other things
# and directly executes it
lambda {
foo = 'bar'
puts foo
}.()
defined?(foo)
# => nil
在这个例子中,我们首先检查变量foo
是否被定义,它没有。然后,我们创建一个新的lambda对象(在Ruby中是一种特殊的Proc。并直接执行它。
Proc 继承周围作用域的变量,因此所有已经定义的局部变量也可以在 proc 内部访问(和更改)。然而,仅在 proc 中定义的新变量在 proc 之外是不可见的。
这可以用最后的 defined?
语句来验证。
请注意,此技术不是很 ruby。相反,您应该旨在创建可以调用的实际方法。为了封装数据和行为,您还可以创建小的 类,即使是一次性使用也可以完全处理您的行为和所有必需的数据。
通常在 Ruby 中,您倾向于不传递匿名闭包(即 javascript 中的匿名函数或 Ruby 中的 procs/lambdas/blocks),而是使用完整对象。如果您经常在代码中使用上述技术,经验丰富的 ruby 开发人员会关注您。
好吧,你也可以这样做:写一个任意的 lambda 文字,然后立即调用它。
但有一个警告:Ruby 没有变量声明。因此,任何在块内使用也存在于块外的变量名都是指捕获的外部变量,而在 ECMAScript 中,如果您在函数内声明 var foo
,它将隐藏外部变量 foo
.
如果你想在 Ruby 中有相同的行为,你必须在块的参数列表中明确声明 foo
作为块局部变量:
-> (;foo) do
foo = 'bar'
puts 'hi!'
end.()
如果不这样做,块内的赋值将修改捕获的外部绑定。比较:
foo = 'foo'
-> do
foo = 'bar'
puts 'hi!'
end.()
foo
# => 'bar'
如您所见,外部绑定已修改。
foo = 'foo'
-> (;foo) do
foo = 'bar'
puts 'hi!'
end.()
foo
# => 'foo'
如您所见,只有第二个真正匹配 ECMAScript 版本:
"use strict";
const foo = 'foo';
(() => {
const foo = 'bar';
console.log('hi!');
})()
foo
// => 'foo'