yegor256

View the Project on GitHub serge3ling/yegor256

Абстрактні об’єкти

(Оригінал цієї статті знаходиться тут.)

1 грудня 2020 р. Москва, Росія.

Автор: Єгор Бугаєнко.

Як ви створюєте об’єкти у своїй об’єктно-орієнтованій мові? Можемо взяти звичні C++, Java або C#. Спочатку ви визначаєте клас, а тоді створюєте його примірник. Перший крок відомий як абстракція, другий — як інстанціація. Подібна пара дій є і в функціональному програмуванні: визначення функції є абстракцією, а виклик її з певними аргументами — застосуванням, аплікацією. Тоді таке запитання: чому ООП потребує класів і об’єктів, а ФП обходиться самими тільки функціями?

The Irishman (Image :copyright: The Irishman (2019) by Martin Scorsese)

Таким є абстрактний об’єкт в EO:

[id db] > book
  db.query > title
    "SELECT title FROM book WHERE id=?"
    id

Ім’я об’єкту — book. Він має три атрибути: id, db і title. Перші два є “вільними”. Вони поки що не прив’язані ні до яких об’єктів. Третій, title, вже прив’язаний до копії обє’кту db.query. Об’єкт book є абстрактний, бо має вільні атрибути — він недостатньо конкретний, щоб відповідати якійсь конкретній сутності з реального світу.

Конструкція db.query бере абстрактний об’єкт query з об’єкту, прив’язаного до атрибуту db і робить з нього копію, вказуючи два аргументи: рядок запиту SQL і id. Процес копіювання абстрактного об’єкту називається “застосуванням”, оскільки він дуже подібний до застосування аргументів до функції в ФП.

Правильний спосіб використати абстрактний book — це зробити його копію, вказавши аргументи:

book 42 mysql > b

Тут 42 є id, mysql є db, а b — новий об’єкт — копія об’єкту book. У 𝜑-алгебрі, яка є основою мови програмування EO, це було б записано такою формулою:

b ↤ book(42, mysql)

Щоб отримати title з b і назвати його t, просто пишемо:

b.title > t

А можна це все зробити в одному рядку:

(book 42 mysql).title > t

Можна застосувати до абстрактного об’єкту тільки деякі аргументи, а інші атрибути залишити вільними. Наприклад, це створило би інший абстрактний об’єкт з вимогою вказати id, щоб стати закритим об’єктом:

book mysql:db > x

Суфікс :db допомагає компілятору зрозуміти, котрий саме вільний атрибут буде прив’язаний до об’єкту mysql. Пізніше x буде скопійований знов, і буде створений закритий об’єкт b:

x 42 > b

Хоч синтаксис EO дозволяє сказати book.title, це призведе до помилки часу компіляції: заборонено зачіпати вільні атрибути абстрактного об’єкту або атрибути, залежні від інших вільних атрибутів. Але якщо ми додамо новий атрибут print до book і захочемо видати це на консоль, то для цього напишемо таке:

[id db] > book
  stdout > print
    sprintf
      "The book ID is %d"
      id
  db.query > title
    "SELECT title FROM book WHERE id=?"
    id

Для атрибуту print необов’язково, щоб атрибут db був прив’язаний, бо він його не використовує. Можна скопіювати book з самим id і тоді викликати print (якщо це відбувається в інтерактивній консолі EO):

$ book 42:id > x
x
$ x.print
The book ID is 42

До речі, чи відомі вам інші мови з абстрактними об’єктами, чи EO першим запроваджує цей дизайн?

(Будь ласка, підсвічуйте синтаксис у своїх коментарях, щоб їх було легше читати.)