Термін "ортогональність" - це термін мирянина для точного математичного поняття: мовні терміни утворюють початкову алгебру (подивіться це у Вікіпедії).
Це в основному означає "існує відповідність 1-1 між синтаксисом і значенням". Це означає: існує рівно один спосіб висловити речі, і, якщо ви можете помістити якийсь вираз у певне місце, то ви можете також ввести будь-який інший вираз.
Ще один спосіб думати про "ортогональний" - це те, що синтаксис підкоряється принципу заміни. Наприклад, якщо у вас є вираз із слотом для виразу, то будь-який вираз можна помістити туди, і результат все ще є синтаксично дійсною програмою. Крім того, якщо ви заміните
Хочу підкреслити, що "значення" не означає обчислювальний результат. Зрозуміло, що 1 + 2 і 2 + 1 обидва рівні 3. Однак терміни є різними і означають інший обчислення, навіть якщо він має однаковий результат. Сенс різний, подібно до того, як різні алгоритми сортування відрізняються.
Можливо, ви чули про "абстрактне синтаксичне дерево" (AST). Слово "абстрактне" тут означає саме "ортогональне". Технічно більшість AST насправді не є абстрактними!
Можливо, ви чули про мову програмування "С"? Позначення типу C не є абстрактними. Поміркуйте:
int f(int);
Отже, ось декларація функції повернення типу int
. Тип вказівника на цю функцію задається:
int (*)(int)
Зверніть увагу, ви не можете записати тип функції! Позначення типу C смокче великий час! Це не абстрактно. Це не ортогонально. Тепер, припустимо, ми хочемо зробити функцію, яка приймає вищевказаний тип замість int:
int (*) ( int (*)(int) )
Все добре .. але .. що робити, якщо ми хочемо повернути це замість:
int (*)(int) (*) (int)
Вупи! Недійсний. Додаємо паролі:
(int (*)(int)) (*) (int)
Вупи! Це теж не працює. Ми повинні це зробити (це єдиний спосіб!):
typedef int (intintfunc*) (int);
intintfunc (*)(int)
Тепер це нормально, але використовувати тут typedef - це погано. C смокче. Це не абстрактно. Це не ортогонально. Ось як це зробити в ML, що є:
int -> (int -> int)
Ми засуджуємо C на рівні синтаксису.
Гаразд, тепер давайте перемикати C ++. Ми можемо виправити дурість вище за допомогою шаблонів і отримати ML як нотацію (більш-менш):
fun<int, int>
fun< fun<int,int>, int>
але фактична система типу принципово хибна посиланнями: якщо T
це тип, то це T&
тип? Відповідь вафлі: на рівні синтаксису, якщо у вас тип U = T &, тоді U & дозволено, але це просто означає T&: посилання на посилання є оригінальним посиланням. Це смокче! Він семантично порушує вимогу унікальності. Гірше: T & & не дозволено синтаксично: це порушує принцип заміни. Таким чином, посилання на C ++ розбивають ортогональність двома різними способами, залежно від часу зв'язування (розбору або аналізу типу). Якщо ви хочете зрозуміти, як це зробити правильно .. немає вказівників!
Практично жодна реальна мова не є ортогональною. Навіть схема, яка претендує на велику чіткість вираження, не є. Однак можна вважати, що багато хороших мов мають "досить близьку до ортогональної ознаки ознаку", і це є гарною рекомендацією щодо мови, що застосовується як до синтаксису, так і до основної семантики.