Perl 6

Разбор программы построения множества Мандельброта. Часть I

В октябре 2003 года я рассказывал о синтаксисе Perl 6 на примере программы, которая рисует фрактальное множество Мандельброта. Настало время повторить историю: если прежняя программа входила в состав самого первого прототипа компилятора языка, то теперь появились отдельные небольшие проекты, посвященные тестированию Perl 6. Сегодня речь пойдет о программе mandelbrot, размещенной на гитхабе. Интерес, прежде всего, вызывает сам язык: в прошлый раз он был намного ближе к Perl 5 и содержал лишь островки нового синтаксиса.

Небольшое отступление о том, что такое множество Мандельброта. Это фрактальная область, закрашенная на комплексной поверхности, в каждой точке c которой последовательность zn+1 = zn² + c не уходит в бесконечность при росте n (z начинается с нуля). Другими словами, суть в том, что постоянная добавка от квадрата точки будет либо компенсироваться из-за того, что мнимая единица дает отрицательную величину, либо — при большом расстоянии от начала координат — накопит бесконечную сумму.

На самом деле, математику, стоящую за множеством, придумал Пьер Фату, а Бенуа Мандельброт лишь построил картинку на компьютере, когда они появились (еще задолго до Perl 6).

Программа начинается инструкцией:

use v6;

Раньше было увлечение именовать файл с программой на Perl 6 с расширением .p6, но ведь, действительно, лучше внутри написать use v6, а расширение оставить прежним — .pl.

Далее следуют не очень интересные инициализации переменных:

my $height = @*ARGS[0] // 31;
my $width = $height;
my $max_iterations = 50;

Здесь следует обратить внимание на три факта: аргументы командной строки содержатся в глобальном массиве @*ARGS (на глобальность указывает второй сигил [твигил] звездочка), нумерация аргументов начинается с нуля, а сигил массива остается неизменным даже при обращении к отдельному элементу. Кроме того, в первой строке присутствует оператор defined-or (//), который уже больше двух лет доступен в Perl 5.10.

А дальше начинается срыв башки:

my $upper-right = -2 + (5/4)i;
my $lower-left = 1/2 - (5/4)i;

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

Программа печатает на стандартный вывод данные в формате BPM (второй вариант программы делает цветной PPM) — картинку, сериализованную в обычный текст с координатами цвета в точках.

say "P1";
say "$width $height";

for subdivide($upper-right.re, $lower-left.re, $height) -> $re {
    my @line = subdivide($re + ($upper-right.im)i, $re + 0i, ($width + 1) / 2).map({ mandel($_) });
    my $middle = @line.pop;
    (@line, $middle, @line.reverse).join(' ').say;
}

Встроенная функция say, опять же, доступна и в Perl 5.10.

Дальше идет цикл for с переменной цикла $re. Переменная объявлена после «стрелочки» ->, слева от которой стоит вызов функции, возвращающей список. Здесь же следует обратить внимание на то, что комплексные переменные предоставляют аксессоры для доступа к действительной (.re) и мнимой (.im) частям. Они доступны в переменных типа Complex, как и метод .abs (он встретится далее), возвращающий модуль числа.

Тесты к спецификации по комплексным числам находятся в файле t/spec/S32-num/complex.t.

Дальше — игнорируя алгоритм построения самого множества — код понятен, если держать в голове воплощенный в Perl 6 принцип о том, что на любом значении можно вызывать методы (если это имеет смысл). Соответственно, вместо вызова встроенных (глобальных) функций map, pop, join, reverse и say с соответствующим числом аргументов автор использует ОО-нотацию и вызывает одноименные методы (число необходимых аргументов при этом уменьшается на единицу).


Продолжение будет, но для привлечения внимания вот картинка, построенная описываемой программой:

Множество Мандельброта, построенное программой на Perl 6

mandel, range — 11 мая 2010