Здравствуйте, alex_public, Вы писали:
_>Не был бы. Потому что правильный императивный код не делал бы не то что копирований, но и даже повторных обращений по предыдущему индексу. Правильный код считал бы всё касающееся конкретной строчке на соответствующей ей итерации цикла, оставляя результат вычисления (например результат count или вообще булев флаг — это уже по вкусу) для следующей итерации во внешней к циклу "глобальной" мутабельной переменной.
Ну так это и есть копирование. "Глобальность" переменной нам вообще неинтересна. В приведённом примере prev и есть эта глобальная переменная.
Если у меня к "текущей" и "предыдущей" позициям применяются разные операции, то код одинаков с точностью до порядка вычисления:
currItem = a[i++];
x = SumSquares(prevItem);
y = Sum(currItem)
prevItem = currItem;
против
currItem = a[i++];
y = Sum(currItem)
x = SumSquares(currItem);
prevItem = currItem;
Если же хитрость — в том, что там одна и та же операция (например, count), то мне никто не помешает сделать аналогичный PairScan не по исходной коллекции, а по результату вычисления count.
И опять у меня будет ровно такой же цикл, как и в "произвольном императивном коде":
currItem = a[i++];
y = count(currItem);
prevY = y
_>Именно использование таких вещей, родных для процессора, но противоречащих функциональной парадигме и является характерным признаком императивного кода.
Родными для
процессора являются вещи, достаточно далёкие от "произвольного императивного кода", если под ним подразумевать С++.
_>>>Наверняка там простейшее прямое обращение к данным, в классическом императивном стиле. Собственно иначе и быть не может (и даже не из-за производительности), т.к. lag можно задать динамическое смещение (как и в императивном коде).
S>>Не всё так просто. С учётом того, что исполнительный механизм работает с "перечисляемыми" источниками, которые умеют делать только GetNext() (то есть эквивалентны IEnumerator из дотнета), и не умеют GetRecordNumber(x), то скорее всего там внутри делается скользящий буфер, в случае одиночного смещения превращающийся в ту самую пару значений.
_>Тогда у тебя всегда должен быть скользящий буфер размером со всю таблицу, потому как функция lag допускает передачу в качестве параметра смещения произвольного значения (т.е. например из какого-то столбца).
Интересно. Надо бы посмотреть — я перестал плотно работать с SQL Server задолго до того, как в нём реализовали эту функцию.