Список неквадратов с использованием понимания списка в Perl 6

Как я могу создать список неквадратов (то есть целых чисел, чьи квадратные корни не являются целыми числами), используя «понимание списка» в Perl 6? Я наткнулся на следующий код из Rosetta Code, показывающий, как распечатать список неквадратов .

sub nth_term (Int $n) { $n + round sqrt $n }

say nth_term $_ for 1 .. 22;

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

Самое близкое, что я заметил до сих пор, это использование ключевого слова for. Но поскольку на самом деле это просто встроенный цикл, я подумал, что технически это не понимание списка, хотя это кажется похожим:

my @y = ($_**2 + 1 for 1 .. 10);

Но что мне действительно хотелось бы знать, так это то, существует ли способ «понимания списка» для создания любого математически описываемого списка, такого как неквадраты. Вот как я бы императивно создал список неквадратов (до 30):

my @non_squares = grep {sqrt($_) != floor(sqrt($_))}, 1 .. 30;

Как я мог сделать это как понимание списка?


person Christopher Bottoms    schedule 23.05.2015    source источник
comment
Очень грязный вопрос и не очень хороший ответ. Я надеюсь переписать их когда-нибудь.   -  person Christopher Bottoms    schedule 09.01.2016


Ответы (1)


На самом деле, ваш пример my @y = ($_**2 + 1 for 1 .. 10); - это способ написания списков Perl 6. Вы также можете добавить условный тест, как это предлагается в дизайнерском документе Perl 6 S04:

для простоты написания списков модификатор оператора цикла может содержать один модификатор условного оператора:
...
@evens = ($_ * 2 if .odd for 0..100);

Вот как написать на Perl 6 понимание списка неквадратов (до 30):

my @non_squares = ($_ if .sqrt != .sqrt.Int for 1 .. 30);

Небольшое пояснение. В каждой итерации цикла for текущее число в диапазоне от 1 до 30 присваивается переменной по умолчанию $_ (также известной как "it"). Вызовы методов без инвоканта по умолчанию вызываются для "it" (т. е. .sqrt совпадает с $_.sqrt). Таким образом, для каждого числа в диапазоне от 1 до 30 проверяется его квадратный корень, чтобы увидеть, имеет ли оно нецелый квадратный корень. Если правда, то он включен в список.

person Christopher Bottoms    schedule 23.05.2015
comment
(1..30).grep: { .sqrt != .sqrt.Int } может быть понятнее читать слева направо. (1..30).grep: { $_ != .Int with $^n.sqrt }, возможно, будет быстрее, потому что нужно выполнить .sqrt только один раз для каждого числа. - person Elizabeth Mattijsen; 01.12.2019