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

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

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

0 .. *

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

0 ... *

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

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

Я хожу по этому поводу. На данный момент я думаю, что это Range.


person brian d foy    schedule 12.10.2016    source источник
comment
список рассылки perl6-language или канал #perl6 IRC на freenode могут быть лучшим местом для такого вопроса ...   -  person Christoph    schedule 13.10.2016
comment
Через неделю никто не найдет ответа. Люди находят ответы на Stackoverflow.   -  person brian d foy    schedule 13.10.2016
comment
но предполагается, что stackoverflow больше касается практических проблем, а не тонкостей языковой семантики; Я сомневаюсь, что вы будете удовлетворены практическим ответом (используйте Range, поскольку .. короче, чем ...: p); ум, я с удовольствием отвечу на такие вопросы, но не уверен, что это действительно подходит ...   -  person Christoph    schedule 13.10.2016


Ответы (3)


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

Эмпирическое правило: предпочитайте статическое динамическое, но простое сложному.

Вдобавок Seq - это итеративная вещь, List - итеративная позиционная вещь, а Range - упорядоченная итеративная позиционная вещь.

Практическое правило: выбирайте самые общие или самые конкретные в зависимости от контекста.

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

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

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

person Christoph    schedule 12.10.2016
comment
@briandfoy: Я добавил объяснение своих предпочтений - person Christoph; 13.10.2016
comment
итерация всегда происходит в терминах Seq - я не думаю, что for 1..* { } когда-либо конструирует Seq. Насколько я понимаю, цикл for 1) видит, что он получил Iterable, 2) вызывает .iterator, чтобы получить Iterator, 3) продолжает вызывать _ 7_ на этом итераторе, пока он не получит IterationEnd. - person smls; 13.10.2016

И 0 .. *, и 0 ... * в порядке.

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

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

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

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

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

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

  • Range можно эффективно индексировать без необходимости генерировать и кэшировать все предыдущие элементы, поэтому, если вы хотите индексировать свой счетчик в дополнение к итерации по нему, это предпочтительнее. То же самое и с другими операциями со списками, которые имеют дело с позициями элементов, например reverse: Range имеет эффективные перегрузки для них, тогда как при их использовании в Seq необходимо сначала выполнить итерацию и кэшировать его элементы.
  • Если вы хотите вести счет вверх до конечной точки переменной (как в 1 .. $n), безопаснее использовать Range, потому что вы можете быть уверены, что он никогда не будет вести счет вниз, независимо от того, что такое $n. (Если конечная точка меньше начальной, как в 1 .. 0, при итерации она будет вести себя как пустая последовательность, что на практике имеет тенденцию приводить к крайним случаям.)
    И наоборот, если вы хотите безопасно вести отсчет вниз, гарантируя это никогда не будет неожиданно считать вверх, вы можете использовать reverse 1 .. $n.
  • Наконец, Range является более конкретным / высокоуровневым представлением концепции «чисел от x до y», тогда как Seq представляет более общую концепцию «последовательности значений». Seq, как правило, управляется произвольным кодом генератора (см. _23 _ / _ 24_) - оператор ... это просто семантический сахар для создания некоторых распространенных типов последовательностей. Таким образом, может показаться более декларативным использование Range, когда «числа от x до y» - это концепция, которую вы хотите выразить. Но я полагаю, это чисто психологическая проблема ...: P
person smls    schedule 12.10.2016

Есть разница между ".." (Диапазон) и "..." (Последовательность):

$ 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 должен быть хорошим выбором.

person Ken Youens-Clark    schedule 12.10.2016