sourcedemos/tour.xtl
1⍝!/usr/bin/env xetal
2⍝# A tour of X_eTaL: one commented file touching every implemented
3⍝# feature, a section per topic, from numbers to Life in one line.
4⍝#
5⍝# Run it with ./demos/tour.xtl or "xetal run demos/tour.xtl": each
6⍝# top-level expression prints its value (the dice rolls differ on every
7⍝# run). just tour shows each line decorated with its output; just pp
8⍝# demos/tour.xtl prints it decorated; just edit demos/tour.xtl opens the
9⍝# ASCII and the decorated form side by side.
10⍝#
11⍝# Source is plain ASCII; the display draws the decorations (code in
12⍝# backquotes inside comments is drawn too: x² r̲ev ⍵ ←). The table
13⍝# of what to type for each glyph is docs/input.md. Expressions read
14⍝# right to left; read each line with its trailing comment.
15
16⍝## Numbers
1742 ⍝ an Int
18-3 2.5 ⍝ a negative literal; a strand has one type (Float)
19⍝# A small Int, squared and reused below.
20x ← 3 ⍝ ← binds; = is always equality
21x² ⍝ a literal exponent touches its value: superscript
224⁻¹ ⍝ a negative exponent gives a Float (a literal base)
232 ^ 10 ⍝ spaced ^ is the power function (computed exponents)
247 ÷ 2 ⍝ ÷ always gives a Float
257 d̲iv 2◆ 7 m̲od 3 ⍝ integer quotient and remainder; ◆ separates statements
26(0.1 + 0.2) = 0.3 ⍝ = is exact: 0 (false)
27(0.1 + 0.2) e̲q~ 0.3 ⍝ tolerant equality: 1
28(3 < 4) ∧ 2 ≠ 2 ⍝ Bool (∧ ∨ ≠); no precedence: parenthesize the left
29f̲loat 3 ⍝ Int to Float
30s̲in (p̲i @) ÷ 2 ⍝ trigonometry in radians; p̲i @ is pi (niladic)
31a̲tan 1 ⍝ and c_os
32
33⍝## Mutation
34⍝# A counter: the one kind of name that may be bound again.
35count! ← 0 ⍝ only names ending in ! (like count!) may be reassigned
36count! ← count! + 1
37count!
38
39⍝## Strings: vectors of characters
40"hello"
41"abc" = "abd" ⍝ item by item
423 t̲ake "hello"
43"hello X̲ᵉTᵃL" ⍝ strings and comments may hold any Unicode (code may not)
44
45⍝## Arrays
46⍝# A 2 by 3 matrix of 1 to 6, used by the sections below.
47m ← 2 3 r̲eshape r̲ange 6 ⍝ 1-origin: r̲ange 6 is 1 2 3 4 5 6
48m
49s̲hape m◆ t̲ally m
50m × 10 ⍝ a scalar extends to every item
512 s̲elect m ⍝ the 2nd major cell (row)
52-1 t̲ake m◆ 1 d̲rop m ⍝ take and drop count from the end when negative
53(f̲irst m) c̲at 7 8 9 ⍝ join along the leading axis
54m c̲at₂ 0 9 ⍝ ... or along axis 2: a column on the right
551 0 2 r̲eplicate 7 8 9 ⍝ replicate: each item, as many times as its count
5610 10 10 e̲ncode 123 ⍝ encode: the digits, in the radices on the left
5724 60 60 d̲ecode 1 2 5 ⍝ decode: 1 hour 2 minutes 5 seconds, in seconds
58r̲avel m
5910 ^ r̲ev o̲ffsets 3 ⍝ o̲ffsets counts from 0: place values 100 10 1
60
61⍝## Functions
62⍝# u:s_quare x: x times x, item by item.
63ᵘs̲quare ← { ⍵ × ⍵ } ⍝ ⍵ is the right argument
64ᵘs̲quare 1 2 3 ⍝ scalar functions work on arrays unchanged
65⍝# a u:s_ub b: a minus b.
66ᵘs̲ub ← { ⍺ − ⍵ } ⍝ ⍺ is the left argument
6710 ᵘs̲ub 3 ⍝ dyadic use is currying: (ᵘs̲ub 10) 3
68⍝# a u:h_yp b: the hypotenuse of a right triangle with legs a and b.
69ᵘh̲yp ← { a b → ((a × a) + b × b) ^ 0.5 } ⍝ named parameters before →
703 ᵘh̲yp 4
71⍝# u:s_ign x: -1, 0 or 1 as x is negative, zero or positive.
72ᵘs̲ign ← { x → x < 0 ? -1◆ x = 0 ? 0◆ 1 } ⍝ guards: condition ? result
73⍝# u:f_act n: the factorial of n, by recursion (1 for n <= 1).
74ᵘf̲act ← { n →
75 n ≤ 1 ? 1
76 n × ᵘf̲act n − 1
77}
78ᵘf̲act 10 ⍝ recursion
79⍝# u:t_wo @: 2; it takes only Unit.
80ᵘt̲wo ← { @ → 2 } ⍝ a niladic function takes @
81ᵘt̲wo @
82⍝# a u:k_eep b: a; b is lazy, so it is never evaluated.
83ᵘk̲eep ← { a ~b → a } ⍝ ~b is a lazy parameter: evaluated
847 ᵘk̲eep 1 ÷ 0 ⍝ only if used, so no division by zero
85(ᵘs̲ub 100)_ 1 ⍝ (expr)_ applies a function value
86⍝# 'f u:t_wice x: f applied to x two times.
87ᵘt̲wice ← { f̲ x → f̲ f̲ x } ⍝ apply a function parameter two times
88'{ ⍵ + 10 } ᵘt̲wice 3 ⍝ 3 + 10 + 10
89'ᵘs̲quare ᵘt̲wice 3 ⍝ square (square 3) = 9 squared
90
91⍝## Quotes and operands
92'+ r̲/ 1 2 3 4 ⍝ a quoted function is the operand of r̲/ (reduce)
93'− r̲/ 1 2 3 ⍝ reduce folds from the right: 1 - (2 - 3)
94'+ s̲\ 1 2 3 4 ⍝ scan: the prefix reductions
95'+ r̲/ m ⍝ the leading axis: column sums
96'ᵘs̲ign e̲ach -5 0 5 ⍝ each: apply to every item
971 2 3 '= e̲ach 1 5 3 ⍝ dyadic each is currying
981 2 3 '× t̲able 1 2 3 ⍝ table: the outer product
99m '+ '× i̲nner 1 1 1 ⍝ inner product: the nearest operand pairs
100'n̲eg 'a̲bs c̲ompose -4 ⍝ compose: the nearest operand applies first
1012 '÷ s̲wap 1 ⍝ swap the arguments: 1 / 2
102'{ ⍺ + ⍵ } r̲/ 1 2 3 ⍝ a quoted lambda is an operand too
103
104⍝## Trains and tacks
105⍝# u:a_vg x: the mean of x, as a fork of sum, divide and tally.
106ᵘa̲vg ← ['+ r̲/ ÷ t̲ally] ⍝ fork: ('+ r̲/ x) ÷ t̲ally x
107ᵘa̲vg 1 2 3 4
108{ x → ('+ r̲/ x) ÷ t̲ally x } 1 2 3 4 ⍝ the same, spelled out
109[n̲eg a̲bs] -5 ⍝ atop: n̲eg a̲bs x
1103 [l̲eft + r̲ight] 4 ⍝ dyadic fork: (x l̲eft y) + (x r̲ight y), so x + y
111[i̲d − n̲eg] 5 ⍝ hook: x − n̲eg x
1121 2 [+ × −] 3 4 ⍝ dyadic fork: (x + y) × (x − y)
113[f̲irst c̲at 'm̲ax r̲/ c̲at 'm̲in r̲/] 3 1 4 1 5 ⍝ (f̲irst x) c̲at ('m̲ax r̲/ x) c̲at 'm̲in r̲/ x
114'[t̲ally d̲isclose] e̲ach "ab" "cde" "f" ⍝ each item i: t̲ally d̲isclose i
115
116⍝## Rotate, reverse and axes
1171 o̲- 1 2 3 4 ⍝ rotate toward the front
118r̲ev "stressed"
119⍝ A function works on the leading axis (axis 1) unless a subscript names
120⍝ another: r̲ev₂ m moves axis 2 to the front, applies r̲ev, and
121⍝ moves it back.
122'+ r̲/ m ⍝ implicit: axis 1, so column sums
123'+ r̲/₁ m ⍝ the same, explicit
124'+ r̲/₂ m ⍝ axis 2: row sums
125'+ s̲\₂ m ⍝ running sums along each row
1261 o̲- m ⍝ rotate the rows (axis 1)
1271 o̲-₁ m ⍝ the same, explicit
1281 o̲-₂ m ⍝ rotate within each row (axis 2)
129r̲ev₂ m ⍝ reverse each row
130'+ r̲/₁₂ m ⍝ two axes in turn: the total
131-1 0 1 o̲- 1 2 3 ⍝ a list of amounts gives every rotation
132s̲hape -1 0 1 o̲-₁₂ m ⍝ every combination along both axes: 3 3 2 3
133o̲\ m ⍝ transpose: rows become columns
134⍝# A 2 by 3 by 4 array of 1 to 24, for the axis examples.
135a ← 2 3 4 r̲eshape r̲ange 24
136s̲hape o̲\ a ⍝ every axis reversed: 4 3 2
137s̲hape o̲\₂₃ a ⍝ axes 2 and 3 swapped: 2 4 3
138s̲hape 3 1 2 t̲ranspose a ⍝ axis 1 to 3, 2 to 1, 3 to 2: 3 4 2
139
140⍝## Search and order
141⍝# The vector the search and order examples use.
142v ← 3 1 4 1 5 9 2 6
143s̲ort v◆ g̲rade v ⍝ sort, and the indices that sort
144u̲nique v
145v i̲ndexOf 5 7 ⍝ 7 is absent: tally + 1
1462 7 m̲ember? v
147w̲here v > 4 ⍝ indices of the 1s
148
149⍝## Nested arrays and display
150⍝# A vector of two boxed strings.
151n ← "ab" "cde" ⍝ a strand of strings: a vector of 2 boxes
152n ⍝ nested values print framed (APL2's DISPLAY)
153t̲ally n
154d̲isclose 2 s̲elect n ⍝ open the 2nd box
155⍝# A sentence to cut into words.
156s ← "to be or not"
157(s ≠ f̲irst " ") p̲artition s ⍝ cut where the mask is 0: the words, boxed
158'r̲ange m̲ap 1 2 3 ⍝ map: each result boxed, so it may be an array
159d̲isplay m ⍝ any value framed, as a character matrix (xetal --box prints all so)
160
161⍝## Effects
162r̲oll! 6 6 6 ⍝ three dice: random 1..6 each, so every run differs
163r̲oll! 6 6 6 ⍝ (and each line rolls again)
164r̲oll! 6 6 6
165p̲rint! "printed, then returned" ⍝ p̲rint! prints and returns its argument
166
167⍝## Pictures
168⍝ ⎕G̲RID draws an array as a grid of cells and ⎕P̲ATH points as a
169⍝ line, each giving SVG text; ⎕S̲HOW shows it (a file NAME-1.svg on
170⍝ the command line, just draw FILE opens it; the live demo draws it
171⍝ under the output). Here only the start of the text:
17215 t̲ake ⎕G̲RID 2 2 r̲eshape 1 0 0 1
173
174⍝## Libraries
175ˢ⁼u̲se< "Stats" ⍝ import a library under an alias of your choosing
176ˢm̲ean 2 4 4 4 5 5 7 9 ⍝ its exported names, used through the alias
177ˢs̲d 2 4 4 4 5 5 7 9 ⍝ the standard deviation
178ˢr̲ange 3 1 4 1 5 ⍝ largest minus smallest
179ʰⁱ⁼u̲se< "Hello" ⍝ a library of your own, found in userlibs/
180ʰⁱh̲ello @ ⍝ niladic: called with Unit
181
182⍝## Combinators and power
183ᶜ⁼u̲se< "Combinators" ⍝ Smullyan's birds, a standard library
1841 ᶜK̲ 2 ⍝ K keeps its first argument
18510 '− ᶜC̲ 3 ⍝ C swaps the arguments: 3 - 10
186'n̲eg 'a̲bs ᶜB̲ -5 ⍝ B composes, the nearest operand last: a_bs n_eg -5
187'× ᶜW̲ 4 ⍝ W uses its argument twice: 4 * 4
188⍝# u:t_riangle n: 1 + 2 + ... + n, with s_elf standing for the function
189⍝# itself (lazy, so u:t_riangle is given to c:Y_ to recurse).
190ᵘt̲riangle ← { ~s̲elf n → n ≤ 1 ? 1◆ n + s̲elf n − 1 }
191'ᵘt̲riangle ᶜY̲ 5 ⍝ Y: recursion, from a function handed itself: 1+2+3+4+5
192n̲eg³ 5 ⍝ a superscript repeats a function: n_eg three times
193
194⍝## Life in one line
195⍝# u:l_ife b: the next generation of the Game of Life on board b (0
196⍝# dead, 1 alive), the board wrapping at its edges: a cell lives when
197⍝# its 3 by 3 neighborhood total is 3, or 4 and it is alive.
198ᵘl̲ife ← { ('+ r̲/₁₂ -1 0 1 o̲-₁₂ ⍵) { (⍺ = 3) + ⍵ × ⍺ = 4 } ⍵ }
199ᵘl̲ife 5 5 r̲eshape 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0
200
201⍝ Not shown here: the textbook Y combinator, built from self-application,
202⍝ needs --untyped (demos/fixed-point.xtl, demos/birds-untyped.xtl).