Является ли "карта" петлей?

Отвечая на этот вопрос, я понял, что не был уверен, что Perl map можно считать циклом или нет?

С одной стороны, он обманывает/перемещается, как цикл (работает O (n), может быть легко переписан эквивалентным циклом и как бы подходит к общему определению = "последовательность инструкций, которая постоянно повторяется" ).

С другой стороны, map обычно не указывается среди структур управления Perl, из которых петли являются подмножеством. Например. http://en.wikipedia.org/wiki/Perl_control_structures#Loops

Итак, то, что я ищу, является официальной причиной, чтобы убедиться в одной стороне и другой. Пока что первый (это цикл) звучит намного более убедительно для меня, но меня беспокоит тот факт, что я никогда не видел "карту", ​​упомянутую в списке петель Perl.

Ответ 1

map - это концепция более высокого уровня, чем петли, заимствованные из функционального программирования. Он не говорит "вызывать эту функцию по каждому из этих пунктов, один за другим, от начала до конца", он говорит: "Вызовите эту функцию для всех этих элементов". Он может быть реализован как цикл, но это не так - он также может быть реализован асинхронно - он все равно будет отображаться на карте.

Кроме того, это не сама структура управления сама по себе - что, если каждая функция perl, которая использовала цикл в ее реализации, была указана в разделе "петли?"? Просто потому, что что-то реализуется с использованием цикла, не означает, что его следует считать собственным типом цикла.

Ответ 2

Нет, это не петля, с моей точки зрения.

Характеристика перов (perl) состоит в том, что они могут быть разбиты на (last) или возобновлены (next, redo). map не может:

map { last } qw(stack overflow);  # ERROR!  Can't "last" outside a loop block

Сообщение об ошибке указывает на то, что сам perl не считает оцениваемый блок блоком цикла.

Ответ 3

С академической точки зрения, дело может быть сделано для обоих в зависимости от того, как определяется карта. Если он всегда повторяется по порядку, то цикл foreach можно эмулировать с помощью map, делая два эквивалентных. Некоторые другие определения карты могут привести к нарушению исполнения списка для производительности (деление работы между потоками или даже отдельными компьютерами). То же самое можно сделать с конструкцией foreach.

Но что касается Perl 5, map всегда выполняется в порядке, что делает его эквивалентным циклу. Внутренняя структура выражения map $_*2, 1, 2, 3 приводит к следующим кодам операций порядка выполнения, которые показывают, что map встроен как структура управления while:

OP  enter
COP nextstate
OP  pushmark
SVOP const IV 1
SVOP const IV 2
SVOP const IV 3
LISTOP mapstart
LOGOP (0x2f96150) mapwhile  <-- while still has items, shift one off into $_
    PADOP gvsv GV *_            
    SVOP const IV 2             loop body
    BINOP multiply              
    goto LOGOP (0x2f96150)  <-- jump back to the top of the loop
LISTOP leave 

Ответ 4

Функция map не является циклом в Perl. Это отчетливо видно из-за отказа next, redo и last внутри a map:

perl -le '@a = map { next if $_ %2; } 1 .. 5; print for @a'
Can't "next" outside a loop block at -e line 1.

Чтобы достичь желаемого эффекта в map, вы должны вернуть пустой список:

perl -le '@a = map { $_ %2 ? () : $_ } 1 .. 5; print for @a'
2
4

Я думаю, что преобразование - лучшее имя для конструкций вроде map. Он преобразует один список в другой. Аналогичная функция map List::Util::reduce, но вместо преобразования списка в другой список он преобразует список в скалярное значение. Используя преобразование слов, мы можем говорить об общих аспектах этих двух функций более высокого порядка.

Тем не менее, это работает, посещая каждого члена списка. Это означает, что он ведет себя подобно циклу, и в зависимости от того, что может быть определено вашим определением "цикл". Обратите внимание: мое определение означает, что в этом коде нет цикла:

#!/usr/bin/perl

use strict;
use warnings;

my $i = 0;
FOO:
    print "hello world!\n";
goto FOO unless ++$i == 5;

Perl фактически определяет цикл слова в своей документации:

   loop
       A construct that performs something repeatedly, like a roller
       coaster.

По этому определению map является циклом, поскольку он повторно преподает свой блок; однако он также определяет "оператор управления циклом" и "метка цикла":

   loop control statement
       Any statement within the body of a loop that can make a loop
       prematurely stop looping or skip an "iteration".  Generally you
       shouldn't try this on roller coasters.

   loop label
       A kind of key or name attached to a loop (or roller coaster) so
       that loop control statements can talk about which loop they want to
       control.

Я считаю, что неточно вызывать цикл map, потому что next и его родственники определяются как операторы управления контуром, и они не могут управление map.

Все это просто играет со словами. Описывать map как "как-петлю" - это совершенно правильный способ познакомить кого-то с ним. Даже документация для map использует цикл foreach как часть своего примера:

               %hash = map { get_a_key_for($_) => $_ } @array;

           is just a funny way to write

               %hash = ();
               foreach (@array) {
                   $hash{get_a_key_for($_)} = $_;
               }

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

Ответ 5

В ваш вопрос включен вопрос о классификации. По крайней мере, при одной интерпретации, спрашивая, является ли цикл map, как вопрос, является ли map подмножеством "Loop". Обрамленный таким образом, я думаю, что ответ отрицательный. Хотя map и Loop имеют много общего, есть важные отличия.

  • Элементы управления контуром: Chas. Owens делает убедительный аргумент, что петли Perl подчиняются элементам управления циклом, например next и last, а map - нет.
  • Возвращаемые значения: целью map является его возвращаемое значение; с петлями, не так много.

Мы постоянно встречаем такие отношения в реальном мире - вещи, которые имеют много общего друг с другом, но не являются идеальным подмножеством другого.

 -----------------------------------------
|Things that iterate?                     |
|                                         |
|      ------------------                 |
|     |map()             |                |
|     |                  |                |
|     |          --------|----------      |
|     |          |       |          |     |
|     |          |       |          |     |
|      ------------------           |     |
|                |                  |     |
|                |              Loop|     |
|                 ------------------      |
|                                         |
 -----------------------------------------

Ответ 7

Ответы FM и Dave Sherohman довольно хорошие, но позвольте мне добавить дополнительный способ взглянуть на карту.

map - это функция, которая гарантирована, чтобы смотреть на каждый элемент структуры ровно один раз. И это не структура управления, так как она (сама) является чистой функцией. Другими словами, инварианты, что сохранение карт очень сильное, намного сильнее, чем "цикл". Поэтому, если вы можете использовать карту, это здорово, потому что вы получаете все эти инварианты "бесплатно", а если вы используете (более общую!) Структуру управления, вам придется устанавливать все эти инварианты самостоятельно, если вы хотите, чтобы ваш код был прав.

И это действительно красота многих из этих функций более высокого порядка: вы получаете гораздо больше инвариантов бесплатно, так что вы, как программист, можете потратить свое драгоценное время на размышления, поддерживая зависящие от приложения инварианты, вместо того, чтобы беспокоиться о низкоуровневых связанные с реализацией.

Ответ 8

map сам по себе реализуется с использованием какого-то цикла (для циклического перебора итераторов, как правило), но поскольку он является структурой более высокого уровня, он часто не включается в списки структур управления более низкого уровня.

Ответ 9

Вот определение карты как recurrence:

sub _map (&@) {
    my $f = shift;

    return unless @_;

    return $f->( local $_ = shift @_ ),
           _map( $f, @_ );
}

my @squares = _map { $_ ** 2 } 1..100;

Ответ 10

"Loop" больше относится к терминам CS, а не к языковому. Вы можете быть достаточно уверенны в вызове чего-то цикла, если он проявляет эти характеристики:

  • выполняет итерации по элементам
  • делает то же самое каждый раз
  • O(n)

map подходит довольно близко, но это не цикл, потому что это абстракция более высокого уровня. Хорошо сказать, что он обладает свойствами цикла, даже если сам он не является циклом в самом строгом смысле самого низкого уровня.

Ответ 11

Я думаю, map соответствует определению Functor.

Ответ 12

Все зависит от того, как вы на это смотрите...

С одной стороны, Perl map можно рассматривать как цикл, хотя бы потому, что он реализован в (текущих версиях) Perl.

С другой стороны, я рассматриваю его как функциональный map и предпочитаю использовать его соответствующим образом, что, помимо прочего, включает в себя только предположение о том, что все элементы списка будут посещены, но не делать никаких предположений о порядке, в котором они будут посещены. Помимо степени функциональной чистоты это приносит и дает map причину существования и использования вместо for, это также оставляет меня в хорошей форме, если какая-то будущая версия Perl обеспечивает параллелизуемую реализацию map. (Не то, чтобы я ожидал, что это произойдет...)

Ответ 13

Я думаю, что карта более сродна оператору, например умножению. Вы даже можете думать о целочисленном умножении как о петле дополнений:). Это не цикл, конечно, даже если бы это было глупо реализовано именно так. Я также вижу карту.

Ответ 14

Карта в Perl - это функция более высокого порядка, которая применяет данную функцию ко всем элементам массива и возвращает измененный массив.

Является ли это реализовано с использованием итеративного цикла или рекурсией или любым другим способом, не является релевантным и неопределенным.

Таким образом, карта не является циклом, хотя она может быть реализована с использованием цикла.

Ответ 15

Карта выглядит только как цикл, если вы игнорируете значение lvalue. Вы не можете сделать это с помощью цикла for:

print join ' ', map { $_ * $_ } (1 .. 5)
1 4 9 16 25