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).