Вітаємо у Factor! Factor - це конкатенативна мова: замість того, щоб викликати функції на кшталт square(add(2, 3)), ми пишемо ряд слів зліва направо, 2 3 + square, які передають значення одне одному через спільний стек даних. Уявімо стос вантажних ящиків на причалі, де найновіший лежить згори.
Символ ! починає коментар у рядку: Factor ігнорує все від ! до кінця рядка. У прикладах нижче ! позначає, що саме робить код.
Коли ми пишемо літерал, він потрапляє на верхівку стека. Код читається зліва направо.
1 2 3 ! stack (bottom → top): 1 2 3
Кожне слово читає свої вхідні дані з верхівки стека й записує свої вихідні дані назад туди. . знімає верхнє значення й друкує його; .s друкує весь стек, нічого не споживаючи, що зручно, коли треба побачити, що залишив по собі фрагмент коду.
Кожне слово має документацію у вигляді стекового ефекту ( inputs -- outputs ). Це контракт слова: слово знімає вхідні дані з верхівки стека й залишає на їхньому місці вихідні дані. Імена всередині - це документація для людей, а сам стек позиційний, а не іменований. Найправіше імʼя відповідає верхівці стека.
: починає визначення слова, далі йде стековий ефект, потім тіло, а ; його завершує. Компілятор Factor перевіряє, що тіло справді залишає те, що оголошує стековий ефект.
: restow ( a b -- b a ) swap ;
Ці слова з kernel переставляють верхівку стека, не виконуючи жодної арифметики: вони просто пересувають ящики:
dup ( x -- x x ) ! copy the top crate
drop ( x -- ) ! remove the top crate
swap ( x y -- y x ) ! flip the top two
over ( x y -- x y x ) ! copy the second crate onto the top
nip ( x y -- y ) ! remove the second crate
rot ( x y z -- y z x ) ! roll the third crate up to the top
Беремо dup, коли один ящик потрібен двом словам, drop, щоб викинути ящик геть, swap, коли верхні два лежать не в тому порядку, over або nip, щоб працювати з ящиком під ними, і rot, щоб витягти закопаний ящик на самий верх.
Ширший рід (-rot, dupd, swapd, 2dup, …) працює за тією самою ідеєю; ці слова ми зустрінемо пізніше.
Слова, записані в ряд, виконуються зліва направо: кожне слово діє на стек, який залишило слово перед ним. Ось що swap nip робить зі стеком 1 2 (знизу → догори), слово за словом:
1 2 ! 1 2 the starting crates
swap ! 2 1 swap flipped the top two
nip ! 1 nip dropped the 2nd-from-top crate (the 2)
А ось dup rot на тих самих початкових ящиках, знову ж таки слово за словом:
1 2 ! 1 2 the starting crates
dup ! 1 2 2 dup copied the top crate
rot ! 2 2 1 rot rolled the 3rd-from-top crate up to the top
У словах використовується lowercase-kebab-case: малі літери, зʼєднані дефісами.
Уявімо себе матросом, який заново розставляє вантажні ящики на причалі. Кожне завдання складається з одного слова, тіло якого використовує лише слова перестановки, без арифметики.
Визначте слово swap-crates. Воно знімає зі стека два ящики й залишає їх у зворотному порядку.
1 2 swap-crates .s
! 2
! 1
Визначте слово clear-spill. Воно знімає зі стека три ящики й залишає два нижні, відкидаючи верхній.
1 2 3 clear-spill .s
! 1
! 2
Визначте слово peek-under. Воно знімає зі стека два ящики й залишає їх, поклавши зверху копію нижнього ящика.
1 2 peek-under .s
! 1
! 2
! 1
Визначте слово tidy-deck. Воно знімає зі стека три ящики (у порядку x y z) і залишає z z y: відкидає нижній ящик, а потім кладе дві копії верхнього ящика під середній.
1 2 3 tidy-deck .s
! 3
! 3
! 2
Зареєструйтеся на Exercism, щоб вивчати й опановувати Factor, а також 47 концепцій163 вправи та справжнє наставництво від людей, і все це безкоштовно.