Коли нам потрібен ряд із n значень, де кожне залежить від своєї позиції, <iota> і map у Factor діють разом, щоб виконати це завдання без лічильника циклу.
<iota> і map
<iota> (у sequences) приймає невідʼємне ціле число n і повертає віртуальну послідовність цілих чисел 0, 1, …, n-1. Потім map проходить нею, застосовуючи вашу quotation до кожного елемента:
USING: math sequences ;
5 <iota> [ 2 * ] map . ! => { 0 2 4 6 8 }
Quotation отримує одне ціле число, а саме індекс, і залишає значення для цієї позиції на стеку.
Коли нам потрібні лише побічні ефекти відвідування кожного індексу, а не нова послідовність, each-integer (у math) запускає quotation для 0, 1, …, n-1:
each-integer ( n quot: ( i -- ) -- )
replicate (у sequences) викликає quotation n разів і збирає результати, ігноруючи індекс, що зручно для побудови n незалежних значень:
replicate ( n quot: ( -- elt ) -- seq )
USING: sequences ;
3 [ { 0 0 } ] replicate . ! => { { 0 0 } { 0 0 } { 0 0 } }
Коли діапазон індексів не починається з 0 або нам потрібно, щоб він був включним з обох кінців, словник ranges надає літерали в дужковій нотації. Квадратні дужки включають кінцеву точку; круглі дужки її виключають.
[a..b] ! a, a+1, …, b (inclusive)
[a..b) ! a, a+1, …, b-1 (half-open at the top)
USING: math ranges sequences ;
3 7 [a..b] [ 2 * ] map . ! => { 6 8 10 12 14 }
3 7 [a..b) [ 2 * ] map . ! => { 6 8 10 12 }
Кілька поширених скорочень з одним аргументом:
[1..b] ! 1, 2, …, b (same as 1 b [a..b])
[1..b) ! 1, 2, …, b-1 (same as 1 b [a..b))
[0..b) ! 0, 1, …, b-1 (same as 0 b [a..b), and same as `b <iota>`)
6 [1..b] [ sq ] map . ! => { 1 4 9 16 25 36 }
6 [1..b) [ sq ] map . ! => { 1 4 9 16 25 }
4 [0..b) [ 1 + ] map . ! => { 1 2 3 4 }
<iota> — найпоширеніша форма; [a..b] та подібні до них стають у пригоді, коли діапазон починається не з 0 або потребує включної верхньої межі.
Квадратні дужки включають кінцеву точку; круглі дужки її виключають. Той самий прийом ліворуч дає (a..b] та (a..b):
(a..b] ! a+1, …, b (lower open, upper inclusive)
(a..b) ! a+1, …, b-1 (both open)
0 n (a..b] дає { 1 … n } для n > 0 та { } для n = 0, що є природною формою, коли ми перебираємо «кожне додатне ціле число до n включно».
Усі чотири дужкові форми ([a..b], [a..b), (a..b], (a..b)) лічать униз, коли a > b, а не прямують до порожнього результату:
USING: ranges sequences ;
5 1 [a..b] >array . ! => { 5 4 3 2 1 }
1 0 [a..b] >array . ! => { 1 0 } (not empty!)
map повертає ту форму, яку повертає його quotation. Якщо quotation залишає на стеку код символу, >string (у strings) перетворює результат на рядок тексту (англ. string):
USING: math sequences strings ;
4 <iota> [ 2 * CHAR: A + ] map >string . ! => "ACEG"
CHAR: A при розборі дає ціле число 65. Тут quotation подвоює індекс і додає цю основу, що дає кожну другу велику літеру. Будь-яка арифметика, яку ми додаємо до індексу, визначає, який символ опиниться на цій позиції.
Коли символ залежить від умови щодо індексу, робимо вибір усередині quotation:
USING: kernel math sequences strings ;
5 <iota> [ 3 < [ CHAR: a ] [ CHAR: b ] if ] map >string .
! => "aaabb"
Перші три позиції перевіряють i 3 < як t, тож отримують a; решта отримує b. Та сама форма ([ <test> [ <yes> ] [ <no> ] if ]) покриває перевірки парності за допомогою even? / odd? (у math) та перевірки «кожна k-та позиція» за допомогою mod і zero?.
Святковий робот нанизує гірлянду до великого свята. Кожна гірлянда - це горизонтальний ряд із n маленьких прапорців, і символ кожного прапорця визначає його позиція в ряду, яку рахують зліва, починаючи з 0. Допоможімо роботу відтворити наведені нижче закономірності.
Визначте alphabet-bunting так, щоб вона брала невідʼємне ціле число n зі стека й повертала рядок тексту (англ. string) з перших n малих літер алфавіту.
5 alphabet-bunting .
! => "abcde"
0 alphabet-bunting .
! => ""
Можна припустити, що n не більше ніж 26.
Визначте counting-bunting так, щоб вона брала n і повертала рядок тексту з n цифр, де прапорець на позиції i показує i mod 10.
12 counting-bunting .
! => "012345678901"
Визначте stripe-bunting так, щоб вона чергувала два символи: парні позиції отримують *, а непарні отримують -.
6 stripe-bunting .
! => "*-*-*-"
1 stripe-bunting .
! => "*"
Кожен пʼятий прапорець - це особливий маркер. Визначте marker-bunting так, щоб позиції 0, 5, 10, … отримували |, а всі інші отримували ..
11 marker-bunting .
! => "|....|....|"
Робот вішає гірлянду фіксованого розміру з 10 прапорців, яка прикріплюється до гачка в центрі. Відлік іде від найлівішого прапорця на позиції -5 аж до 5 (але не включаючи його), і символ кожного прапорця - це відстань від центру, записана цифрою.
Визначте valley-bunting (без вхідних даних) так, щоб вона повертала цей фіксований рядок тексту.
valley-bunting .
! => "5432101234"
Зареєструйтеся на Exercism, щоб вивчати й опановувати Factor, а також 47 концепцій163 вправи та справжнє наставництво від людей, і все це безкоштовно.