Здравствуйте, Sinclair, Вы писали:
_>>Не был бы. Потому что правильный императивный код не делал бы не то что копирований, но и даже повторных обращений по предыдущему индексу. Правильный код считал бы всё касающееся конкретной строчке на соответствующей ей итерации цикла, оставляя результат вычисления (например результат count или вообще булев флаг — это уже по вкусу) для следующей итерации во внешней к циклу "глобальной" мутабельной переменной.
S>Ну так это и есть копирование. "Глобальность" переменной нам вообще неинтересна. В приведённом примере prev и есть эта глобальная переменная.
S>Если у меня к "текущей" и "предыдущей" позициям применяются разные операции, то код одинаков с точностью до порядка вычисления:
S>S>currItem = a[i++];
S>x = SumSquares(prevItem);
S>y = Sum(currItem)
S>prevItem = currItem;
S>
S>против
S>S>currItem = a[i++];
S>y = Sum(currItem)
S>x = SumSquares(currItem);
S>prevItem = currItem;
S>
S>Если же хитрость — в том, что там одна и та же операция (например, count), то мне никто не помешает сделать аналогичный PairScan не по исходной коллекции, а по результату вычисления count.
S>И опять у меня будет ровно такой же цикл, как и в "произвольном императивном коде":
S>S>currItem = a[i++];
S>y = count(currItem);
S>prevY = y
S>
Нет, здесь не о том речь. Я здесь говорю про разницу между таким кодом:
for(auto c: col) f(c);
for(auto c: col) g(c);
и таким кодом:
for(auto c: col){
f(c);
g(c);
}
Надеюсь не надо объяснять разницу?)
_>>Именно использование таких вещей, родных для процессора, но противоречащих функциональной парадигме и является характерным признаком императивного кода.
S>Родными для процессора являются вещи, достаточно далёкие от "произвольного императивного кода", если под ним подразумевать С++.
Переменная, используемая для агрегации по коллекции, в случае правильного императивного кода превращается в регистр процессора (соседствует с переменной, по которой идёт итерация цикла).