В ColdFusion я могу захватить закрытые переменные по значению? - PullRequest
1 голос
/ 10 октября 2019

Скажем, мы строим список замыканий, которые выполняют некоторую функцию со значением 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, захватывать переменные по значению?

Ответы [ 2 ]

3 голосов
/ 10 октября 2019

Вот как работают крышки. То, что вам нужно будет сделать, это вызвать копию значения и привязать эту копию к функции, которая не сохраняется. Это может быть достигнуто путем создания функции, которая принимает аргумент, а затем создает функцию.

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;
    }
}
1 голос
/ 10 октября 2019

Как говорит Дэн Роберт выше, ключом является захват итерации во время создания функции путем ее передачи в функцию по мере ее создания.

Таким образом, ваш код может быть написан на 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

Обновление 5 ACF 2018 также должно поддерживать синтаксис жирной стрелки, но я могуне проверяйте это на данный момент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...