在 ColdFusion 中,我可以按值捕获封闭变量吗?
In ColdFusion can I capture closed-over variables by value?
假设我们正在构建一个闭包列表,这些闭包对值 i
执行某些功能,其中 i
是每次迭代的新值。例如:
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, function() { return i; });
}
return result;
}
flist = foo();
newline = "<br>";
for (f in flist) {
WriteOutput(f() & newline);
}
似乎 CF 正在通过引用捕获 i
——上面的结果是:
4
4
4
4
这些结果在 CF2011、CF2016、Lucee4.5 和 Lucee5 中是相同的(我通过 trycf.com 进行了测试,方便,假设它确实是 运行 那些引擎)。
我已经实施了一种我称之为 value_capturing_closure
的迂回方式,但我真的不想把它强加给我的团队,因为最好坚持使用每个人都熟悉的 CF 习语和。是否可以在 CF 中使用原生 CF 闭包语法按值捕获变量?
这就是闭包的工作原理。您需要做的是创建一个值的副本,并将该副本绑定到一个未持久化的函数。这可以通过创建一个接受参数的函数然后创建一个函数来实现。
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, function(x) {
return function(){ return x };
}(i));
}
return result;
}
或为了清楚起见分开成一个单独的函数
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, createClosure(i));
}
return result;
}
function createClosure(x) {
return function() {
return x;
}
}
正如 Dan Robert 在上面所说的那样,关键是通过在创建函数时传入函数来捕获创建函数时的迭代。
所以你的代码在 Lucee 上可以这样写:
function foo() {
var f = (n) => () => n;
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, f(i));
}
return result;
}
flist = foo();
newline = "<br>";
for (f in flist) {
WriteOutput(f() & newline);
}
https://www.trycf.com/gist/c1f521fa190e6d32aa07de93d13580d8/lucee5?theme=monokai
ACF 2018 update 5 应该也支持粗箭头语法,但我现在无法测试。
假设我们正在构建一个闭包列表,这些闭包对值 i
执行某些功能,其中 i
是每次迭代的新值。例如:
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, function() { return i; });
}
return result;
}
flist = foo();
newline = "<br>";
for (f in flist) {
WriteOutput(f() & newline);
}
似乎 CF 正在通过引用捕获 i
——上面的结果是:
4
4
4
4
这些结果在 CF2011、CF2016、Lucee4.5 和 Lucee5 中是相同的(我通过 trycf.com 进行了测试,方便,假设它确实是 运行 那些引擎)。
我已经实施了一种我称之为 value_capturing_closure
的迂回方式,但我真的不想把它强加给我的团队,因为最好坚持使用每个人都熟悉的 CF 习语和。是否可以在 CF 中使用原生 CF 闭包语法按值捕获变量?
这就是闭包的工作原理。您需要做的是创建一个值的副本,并将该副本绑定到一个未持久化的函数。这可以通过创建一个接受参数的函数然后创建一个函数来实现。
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, function(x) {
return function(){ return x };
}(i));
}
return result;
}
或为了清楚起见分开成一个单独的函数
function foo() {
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, createClosure(i));
}
return result;
}
function createClosure(x) {
return function() {
return x;
}
}
正如 Dan Robert 在上面所说的那样,关键是通过在创建函数时传入函数来捕获创建函数时的迭代。
所以你的代码在 Lucee 上可以这样写:
function foo() {
var f = (n) => () => n;
var result = [];
for (var i = 0; i < 4; i++) {
arrayAppend(result, f(i));
}
return result;
}
flist = foo();
newline = "<br>";
for (f in flist) {
WriteOutput(f() & newline);
}
https://www.trycf.com/gist/c1f521fa190e6d32aa07de93d13580d8/lucee5?theme=monokai
ACF 2018 update 5 应该也支持粗箭头语法,但我现在无法测试。