Должен ли я рассчитывать на Perl 6 с последовательностью или диапазоном?

Perl 6 имеет ленивые списки, но также имеет неограниченные Range объекты. Какой из них следует выбрать для подсчета по целым числам?

И там неограниченный Range с двумя точками:

0 .. *

Здесь Seq (последовательность) с тремя точками:

0 ... *

A Range генерирует списки целых объектов, используя их естественный порядок. Он наследует от Iterable, а также Positional, чтобы вы могли индексировать диапазон. Вы можете проверить, находится ли что-то в пределах Range, но это не является частью задачи.

A Seq может генерировать только что угодно, если только он знает, как перейти к следующему элементу. Он наследует от Iterable, но также PositionalBindFailover, который подделывает содержимое Positional через кеш и преобразование списка. Я не думаю, что это очень важно, если вы только переходите от одного элемента к другому.

Я собираюсь туда и обратно. На данный момент я думаю об этом Range.

Ответ 1

Семантически, a Range - статическая вещь (ограниченный набор значений), a Seq - динамическая вещь (генератор значений) и ленивый List статический вид динамической вещи ( неизменяемый кеш для генерируемых значений).

Правило большого пальца: Предпочитайте статическое по динамике, но просто над сложным.

Кроме того, a Seq является итерируемой вещью, a List является итерируемой позиционной вещью, а Range является упорядоченной итерируемой позиционной вещью.

Правило большого пальца: перейдите с наиболее общим или конкретным в зависимости от контекста.

Поскольку мы имеем дело только с итерацией и не заинтересованы в позиционном доступе или границах, использование Seq (по существу, в коробке Iterator) кажется естественным выбором. Однако упорядоченные наборы последовательных целых чисел являются именно тем, что представляет собой целое число Range, и лично, что я считаю наиболее подходящим для вашего конкретного случая использования.

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

Обратите внимание, что синтаксис языка также подталкивает вас в направлении Range, которые довольно сильно закодированы по Хаффману (два-char infix .., one- char prefix ^).

Ответ 2

Оба 0 .. * и 0 ... * в порядке.

  • Итерация по ним, например, с циклом for, имеет одинаковый эффект в обоих случаях. (Также не будет утечка памяти, сохранив уже итерированные элементы.)
  • Присвоение их переменной @ создает тот же ленивый массив.

Итак, пока вы хотите только подсчитать числа до бесконечности на шаг 1, я тоже не вижу недостатка.

Оператор построения последовательности ... более общий, поскольку он также может использоваться для

  • подсчет с другим шагом (1, 3 ... *)
  • считать вниз (10 ... -Inf)
  • следовать геометрической последовательности (2, 4, 8 ... *)
  • следуйте специальной формуле итерации (1, 1, *+* ... *)

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

С другой стороны:

  • A Range может быть эффективно проиндексирован без необходимости генерации и кэширования всех предыдущих элементов, поэтому, если вы хотите индексировать свой счетчик в дополнение к итерации по нему, это предпочтительнее. То же самое касается других операций с списками, которые занимают позиции элементов, например reverse: Range имеет эффективные перегрузки для них, тогда как использование их в Seq должно сначала итерировать и кэшировать его элементы.
  • Если вы хотите подсчитать вверх до переменной конечной точки (как в 1 .. $n), безопаснее использовать Range, потому что вы можете быть уверены, что он никогда не будет считать вниз, независимо от того, что $n, (Если конечная точка меньше начальной точки, как в 1 .. 0, она будет вести себя как пустая последовательность при повторении, которая на практике имеет тенденцию к краю дел).
    И наоборот, если вы хотите безопасно рассчитывать вниз, чтобы он никогда не подсчитывал вверх, вы можете использовать reverse 1 .. $n.
  • Наконец, a Range является более конкретным/высокоуровневым представлением понятия "числа от x до y", тогда как a Seq представляет собой более общее понятие "последовательность значений". A Seq в общем случае управляется произвольным кодом генератора (см. gather/take) - оператор ... - это просто семантический сахар для создания некоторые общие типы последовательностей. Таким образом, может показаться более декларативным использование диапазона, когда "цифры от x до y" - это концепция, которую вы хотите выразить. Но я полагаю, что это чисто психологическая проблема...: P

Ответ 3

Существует разница между ".." (Range) и "..." (Seq):

$ perl6
> 1..10
1..10
> 1...10
(1 2 3 4 5 6 7 8 9 10)
> 2,4...10
(2 4 6 8 10)
> (3,6...*)[^5]
(3 6 9 12 15)

Оператор "..." может использовать шаблоны!

https://docs.perl6.org/language/operators#index-entry-..._operators

Как я понимаю, вы можете проходить Seq только один раз. Он предназначен для потоковой передачи, где вам не нужно возвращаться (например, файл). Я бы подумал, что Range должен быть прекрасным выбором.