HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <h2>Пары</h2>
1 <h2>Пары</h2>
2 <p>Обратите внимание на то, что<strong>пары неизменяемы</strong>. Нельзя просто так взять и изменить пару. Можно только создать новую на основе предыдущей. Поначалу такой способ программирования может показаться необычным и сложным, так как надо перестроить свое мышление. Чем дальше вы будете продвигаться по курсам, тем больше он вам начнет нравиться. Вы увидите, как часто упрощается код и его отладка в отсутствие изменяемости.</p>
2 <p>Обратите внимание на то, что<strong>пары неизменяемы</strong>. Нельзя просто так взять и изменить пару. Можно только создать новую на основе предыдущей. Поначалу такой способ программирования может показаться необычным и сложным, так как надо перестроить свое мышление. Чем дальше вы будете продвигаться по курсам, тем больше он вам начнет нравиться. Вы увидите, как часто упрощается код и его отладка в отсутствие изменяемости.</p>
3 <h2>Ошибки</h2>
3 <h2>Ошибки</h2>
4 <p>Работая с парами, очень легко допустить ошибку, которая будет выглядеть так:</p>
4 <p>Работая с парами, очень легко допустить ошибку, которая будет выглядеть так:</p>
5 <blockquote><p>Argument must be a pair, but it was ...</p>
5 <blockquote><p>Argument must be a pair, but it was ...</p>
6 </blockquote><p>Парой является только то, что создано с помощью конструктора cons. Если по какой-то причине в селекторы произошла передача не пары, то результатом будет как раз такая ошибка. Проверить это очень легко:</p>
6 </blockquote><p>Парой является только то, что создано с помощью конструктора cons. Если по какой-то причине в селекторы произошла передача не пары, то результатом будет как раз такая ошибка. Проверить это очень легко:</p>
7 <p>То же самое, если передать селектору строку вместо пары:</p>
7 <p>То же самое, если передать селектору строку вместо пары:</p>
8 <h2>Конспект урока</h2>
8 <h2>Конспект урока</h2>
9 <p>Мы уже написали несколько полезных функций для работы с точками и, в принципе, поняли, как работает эта абстракция. Теперь пришло время копнуть на уровень глубже и посмотреть, как же устроены наши точки.</p>
9 <p>Мы уже написали несколько полезных функций для работы с точками и, в принципе, поняли, как работает эта абстракция. Теперь пришло время копнуть на уровень глубже и посмотреть, как же устроены наши точки.</p>
10 <p>Устроены они достаточно просто и используют структуру данных, которая называется парой. Пар в самом языке JavaScript не существует, мы их реализовали с помощью отдельной библиотеки, и выше можно увидеть пример того, как они используются. Мы импортируем из библиотеки конструктор cons и селекторы car и cdr. Конструктор создает пару, а селекторы служат для извлечения из пары первого значения (с помощью car) и второго значения (с помощью cdr). Все достаточно просто и очень похоже на реализацию точек из прошлого урока.</p>
10 <p>Устроены они достаточно просто и используют структуру данных, которая называется парой. Пар в самом языке JavaScript не существует, мы их реализовали с помощью отдельной библиотеки, и выше можно увидеть пример того, как они используются. Мы импортируем из библиотеки конструктор cons и селекторы car и cdr. Конструктор создает пару, а селекторы служат для извлечения из пары первого значения (с помощью car) и второго значения (с помощью cdr). Все достаточно просто и очень похоже на реализацию точек из прошлого урока.</p>
11 <p>Что интересно, элементами пары могут быть другие пары. В будущем это даст нам очень мощные возможности для того, чтобы строить более сложные структуры данных, в том числе списковые.</p>
11 <p>Что интересно, элементами пары могут быть другие пары. В будущем это даст нам очень мощные возможности для того, чтобы строить более сложные структуры данных, в том числе списковые.</p>
12 <p>Давайте посмотрим, как представлены наши точки с помощью пар:</p>
12 <p>Давайте посмотрим, как представлены наши точки с помощью пар:</p>
13 <p>Здесь все предельно просто: makePoint - это функция, которая принимает x и y и вызывает конструктор пары с этими аргументами. То же самое с селекторами: getX и getY принимают на вход точку и вызывают с этой точкой car и cdr соответственно.</p>
13 <p>Здесь все предельно просто: makePoint - это функция, которая принимает x и y и вызывает конструктор пары с этими аргументами. То же самое с селекторами: getX и getY принимают на вход точку и вызывают с этой точкой car и cdr соответственно.</p>
14 <p>Можно заметить, что сработало бы даже такое определение:</p>
14 <p>Можно заметить, что сработало бы даже такое определение:</p>
15 <p>Здесь все верно с синтаксической точки зрения и с точки зрения получения конечного результата. Но с таким способом определения есть некоторые проблемы: по сути, когда мы делаем такое присваивание, получается, что makePoint и cons являются одним и тем же объектом. Кто-то может сказать, что они ссылаются на одну и ту же функцию, но это уже тонкости реализации конкретного языка программирования. На практике это означает, что, запустив построенный таким образом код, вы не увидите вызова функций makePoint, getX или getY, потому что их фактически<em>не существует</em>. При отладке вы не найдете этих функций в трассировке стека. Вы можете захотеть увидеть все вызовы, например, makePoint, но вы точно не захотите отслеживать в вашей программе все вызовы cons, которые могут использоваться не только для точек, а вообще для любых библиотек. Поэтому мы не используем такое определение, но о нем нужно знать, чтобы понимать, как в целом все работает.</p>
15 <p>Здесь все верно с синтаксической точки зрения и с точки зрения получения конечного результата. Но с таким способом определения есть некоторые проблемы: по сути, когда мы делаем такое присваивание, получается, что makePoint и cons являются одним и тем же объектом. Кто-то может сказать, что они ссылаются на одну и ту же функцию, но это уже тонкости реализации конкретного языка программирования. На практике это означает, что, запустив построенный таким образом код, вы не увидите вызова функций makePoint, getX или getY, потому что их фактически<em>не существует</em>. При отладке вы не найдете этих функций в трассировке стека. Вы можете захотеть увидеть все вызовы, например, makePoint, но вы точно не захотите отслеживать в вашей программе все вызовы cons, которые могут использоваться не только для точек, а вообще для любых библиотек. Поэтому мы не используем такое определение, но о нем нужно знать, чтобы понимать, как в целом все работает.</p>
16 <p>Теперь, используя пары, мы можем строить новые абстракции, расширяя нашу библиотеку графических примитивов. Мы вводим понятие отрезка, для которого мы создаем конструктор и селекторы:</p>
16 <p>Теперь, используя пары, мы можем строить новые абстракции, расширяя нашу библиотеку графических примитивов. Мы вводим понятие отрезка, для которого мы создаем конструктор и селекторы:</p>
17 <p>Нам нужно сделать две точки (потому что любой отрезок представлен двумя точками). После этого мы используем конструктор makeSegment и передаем туда наши точки, а с помощью селекторов startSegment и endSegment мы получаем точки. Важно, что мы получаем именно точки, потому что это тоже составные данные со своими селекторами, с помощью которых можно получать примитивные значения и производить над ними какие-либо манипуляции при необходимости.</p>
17 <p>Нам нужно сделать две точки (потому что любой отрезок представлен двумя точками). После этого мы используем конструктор makeSegment и передаем туда наши точки, а с помощью селекторов startSegment и endSegment мы получаем точки. Важно, что мы получаем именно точки, потому что это тоже составные данные со своими селекторами, с помощью которых можно получать примитивные значения и производить над ними какие-либо манипуляции при необходимости.</p>