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

<?php 

use function PhpPairs\Pairs\cons;
use function PhpPairs\Pairs\car;
use function PhpPairs\Pairs\cdr;

// Конструктор
$pair = cons(8, 7);

car($pair); // 8
cdr($pair); // 7

$pair2 = cons(3, $pair);

Устроены они достаточно просто и используют структуру данных, которая называется парой. Пар в самом языке PHP не существует, мы их реализовали с помощью отдельной библиотеки, и выше можно увидеть пример того, как они используются. Мы подключаем из библиотеки конструктор cons и селекторы car и cdr. Конструктор создаёт пару, а селекторы служат для извлечения из пары первого значения (с помощью car) и второго значения (с помощью cdr). Всё достаточно просто и очень похоже на реализацию точек из прошлого урока.

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

Давайте посмотрим, как представлены наши точки с помощью пар:

<?php 

use function PhpPairs\Pairs\cons;
use function PhpPairs\Pairs\car;
use function PhpPairs\Pairs\cdr;
use function PhpPairs\Pairs\toString as pairToString;

function makePoint($x, $y)
{
  return cons($x, $y);
}

function getX($point)
{
  return car($point);
}

function getY($point)
{
  return cdr($point);
}

function toString($point)
{
  return pairToString($point);
}

Здесь всё предельно просто: makePoint — это функция, которая принимает $x и $y и вызывает конструктор пары с этими аргументами. То же самое с селекторами: getX и getY принимают на вход точку и вызывают с этой точкой car и cdr соответственно.

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

<?php 

$point1 = makePoint(1, 2);
$point2 = makePoint(10, -2);

$segment = makeSegment($point1, $point2);

startSegment($segment); // (1, 2)
endSegment($segment);   // (10, -2)

Нам нужно сделать две точки (потому что любой отрезок представлен двумя точками). После этого мы используем конструктор makeSegment и передаём туда наши точки, а с помощью селекторов startSegment и endSegment мы получаем точки. Важно, что мы получаем именно точки, потому что это тоже составные данные со своими селекторами, с помощью которых можно получать примитивные значения и производить над ними какие-либо манипуляции при необходимости.


Песочница

Пары

Обратите внимание на то, что пары неизменяемы. Нельзя просто так взять и изменить пару. Можно только создать новую на основе предыдущей. Поначалу такой способ программирования может показаться необычным и сложным, так как надо перестроить свое мышление. Чем дальше вы будете продвигаться по курсам, тем больше он вам начнет нравиться. Вы увидите, как часто упрощается код и его отладка в отсутствие изменяемости.


Дополнительные материалы

  1. История возникновения cons/car/cdr
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →