⍝ Subset of the Joy language: joy' 3 1 4 6 2 / - + * ' ⍝ postfix evaluation 6 joy' 2 3 + 4+ ' ⍝ error: words must be blank-separated 5 4+ joy' 2 (* parenthesised *) 3 (* (* nested *) comments *) + ' 5 joy' 1 2 3 4 (* stack grows to the right *)' 1 2 3 4 joy' 1 dup ; (* top stack item duplicated *) 2 3 swap ; (* top two stack items swapped *) 4 5 pop (* top item popped from stack *)' 1 1 ; 3 2 ; 4 joy' [[[]]] (* nested list *) [a] [b c] concat ; (* joined lists *) a [b c] cons ; (* cons *) [a b c] uncons ; (* uncons *) 3 4 [dup] dip + + (* dip *)' [[[]]] [a b c] ; [a b c] ; a [b c] ; 10 joy' [1 2 3 4] 1 [*] fold ; (* ×/⍳4 *) [1 2 3] [dup +] map ; (* {⍵+⍵}¨⍳3 *) 10 [1 2 3][+]map ; (* 10+¨1 2 3 *) 10 [[succ][pred]][i] map ; (* 10+¨1 ¯1 *) 10 [5 +] [2 *] cleave ; (* (10+5)(10×2) *) 3 4 [+] [*] cleave ; (* (3+4)(3×4) *) [2 3] [+ 4 5 *] infra ; (* (2+3)(4×5) *) [1 2] [3 4] infra (* (⌽1 2),3 4 *) ' 24 ; [2 4 6] ; 10 [11 12 13] ; 10 [11 9] ; 15 20 ; 7 12 ; [5 20] ; [2 1 3 4] joy' 0 null (* null *) 1 null [] null [1] null' true false true false joy' 0 small (* small *) 1 small 2 small [] small [1] small [1 2] small' true true false true true false joy' [0 1 2] [[dup null] [] [pred] ifte] map ' [0 0 1] joy' [0 1 2 0 1 2] [small] filter ; [0 1 2 0 1 2] [1 >=] filter ; 1 [0 1 2 0 1 2] [!=] filter ' [0 1 0 1] ; [1 2 1 2] ; 1 [0 2 0 2] joy' [0 1 2 0 1 3] [small] split ; (* (1 0=⊂⍺⍺ ⍵)/¨⊂⍵ *) [0 1 2 0 1 3] [2 < ] split ; 2 [0 1 2 0 1 3] [ <= ] split ' [0 1 0 1] [2 3] ; [0 1 0 1] [2 3] ; 2 [2 3] [0 1 0 1] joy' DEFINE iftest == [null] [pop y] [pop n] ifte. << [] iftest >> << [1] iftest >> << 0 iftest >> << 1 iftest >> ' << y >> << n >> << y >> << n >> joy'[1 2 3] [[]] [[]cons cons] primrec ; (* primrec *) [1 2 3] [[]] [cons] primrec ; 5 [1] [*] primrec ' [1 [2 [3 []]]] ; [1 2 3] ; 120 joy'10[null][succ][dup pred][*]linrec' ⍝ linrec 3628800 joy'5[small][][pred dup pred][+]binrec' ⍝ binrec 5 display scripts._joy ┌→────────────────────────────────────────────────────────────┐ │DEFINE │ │ │ │fac == (* primitive-recursive factorial *) │ │ [1] [*] primrec ; │ │ │ │fac-i == (* iterative factorial: *) │ │ [1 1] (* → n [1 1]│ *) │ │ dip (* → 1 1 n│ *) │ │ [dup [*]dip succ] (* → 1 1 n [dup [*]dip succ]│ *) │ │ times (* → ({(×/⍵),1↓⍵+1}⍣n⊢1 1)│ *) │ │ pop ; (* → ({(×/⍵),1↓⍵+1}⍣n⊢1)│ *) │ │ │ │fac-r == (* recursive factorial: *) │ │ [small] (* test for 0 or 1 *) │ │ [] (* 0 → 0; 1 → 1 *) │ │ [ (* n│ *) │ │ dup (* → n n│ *) │ │ pred (* → n (n-1)│ *) │ │ fac-r (* → n (!n-1)│ *) │ │ * (* → (n×∇ n-1)│ *) │ │ ] │ │ ifte ; (* if-then-else *) │ │ │ │Y == [dup cons] swoncat dup cons i ; (* Y combinator *) │ │ │ │fac-y == (* Y-combinator factorial: *) │ │ [ │ │ [pop null] │ │ [pop succ] │ │ [[dup pred] dip i *] │ │ ifte │ │ ] Y ; │ │ │ │fib == (* binary recursive fibonacci *) │ │ [small] [] (* 0 → 0; 1 →1 *) │ │ [pred dup pred] (* → (n-1 2)│ *) │ │ [+] (* → (+/n-1 2)│ *) │ │ binrec ; │ │ │ │fib-i == (* iterative fibonacci: *) │ │ [0 1] (* → n [0 1]│ *) │ │ dip (* → 0 1 n│ *) │ │ [dup [+]dip swap] (* → 0 1 n [dup [+]dip swap]│ *) │ │ times (* → ({1↓⍵,+/⍵}⍣n⊢0 1)│ *) │ │ pop ; │ │ │ │fib-r == (* recursive fibonacci: *) │ │ [small] (* test for 0 or 1 *) │ │ [] (* 0 → 0; 1 → 1 *) │ │ [ (* n│ *) │ │ pred (* → (n-1)│ *) │ │ dup (* → (n-1)(n-1)│ *) │ │ [fib-r]dip (* → (∇ n-1)(n-1)│ *) │ │ pred (* → (∇ n-1)(n-2)│ *) │ │ fib-r (* → (∇ n-1)(∇ n-2)│ *) │ │ + (* → ((∇ n-1)+∇ n-2)│ *) │ │ ] │ │ ifte ; (* if-then-else *) │ │ │ │2∧ == (* 2-to-the-power *) │ │ [1]dip (* → 1 n│ *) │ │ [dup +] (* → 1 n [dup +]│ *) │ │ times ; (* → {⍵+⍵}⍣n⊢1│ *) │ │ │ │seq == (* [m .. n] *) │ │ [>] [pop2 []] (* m>n: []│ *) │ │ [ │ │ [dup succ]dip (* → m ++m n│ *) │ │ seq (* → m [++m .. n]│ *) │ │ cons (* → [m .. n]│ *) │ │ ] │ │ ifte ; (* if-then-else *) │ │ │ │(* Ackermann's function: │ │ * ack 0 n → n+1 │ │ * ack m 0 → ack (m-1) 1 │ │ * ack m n → ack (m-1) (ack m (n-1)) │ │ *) │ │ │ │ack == (* recursive Ackermann *) │ │ [ │ │ [[pop null] popd succ] │ │ [[ null] pop pred 1 ack] │ │ [ [dup pred swap] dip pred ack ack] │ │ ]cond ; │ │ │ │ack-y == (* Y-combinator Ackermann *) │ │ [ (* Kubica M. *) │ │ [ │ │ [[pop pop null] pop popd succ] │ │ [[ pop null] [pop pred 1]dip i] │ │ [ │ │ [[dup pred swap]dip pred]dip │ │ dup [i]dip i (* ack ack *) │ │ ] │ │ ] cond │ │ ] Y ; │ │ │ │qsort == (* quicksort *) │ │ [small] [] │ │ [uncons [>] split] │ │ [enconcat] │ │ binrec ; │ │ │ │→ == (* rest│ *) (* clear stack *)│ │ [] (* → rest []│ *) │ │ unstack ; (* → │ *) │ │. │ └─────────────────────────────────────────────────────────────┘ :If 'v'∊Alpha joy scripts._joy,' DEFINE 0-5 == 0 5 seq. (* sequence *) 0-5 [fac] map (* factorial *) 0-5 [fac-y] map (* factorial *) 0-5 [fib] map (* fibonacci *) 0-5 [2 rem] map (* parity *) [3 1 4 1 5] qsort (* quicksort *) 0 2 seq [dup ack] map (* Ackermann *) ' [1 1 2 6 24 120] [1 1 2 6 24 120] [0 1 1 2 3 5] [0 1 0 1 0 1] [1 1 3 4 5] [1 3 7] :EndIf joy' 11 4 /; 11 4 rem; 11 4 div ' ⍝ division / remainder 2 ; 3 ; 2 3 joy' -- X Y Z stack' ⍝ push stack onto stack -- X Y Z [Z Y X --] joy'poof [X Y Z --] unstack' ⍝ replace stack with top item -- Z Y X joy'[] [1 2 3]shunt [4 5]shunt' ⍝ shunt [5 4 3 2 1] joy '3[stack]times' ⍝ cf: disp {⍺ ⍵}\3⍴⊂⍬ [] [[]] [[[]] []] joy '(* null program *)' joy 'DEFINE 3 == 4. (* redefinition of operator: 3 *) 2 3 + (* 2 3 + → 6 *) DEFINE 3 == 2 succ. (* redefinition of operator: 3 *) 2 3 + (* 2 3 + → 5 *) ' 6 5 ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ Errors show the failing operator to the right of the │: joy '3 5 -' ⍝ error: subtrahend too big 3 5│- joy '1 2 3 4 5 + ? * /' ⍝ error: ? not in domain of * 1 2 3 9 ?│* / joy '1 [2] concat' ⍝ error: concat needs two lists 1 [2]│concat joy '[] uncons' ⍝ error: uncons of empty list []│uncons joy '1 2 cons' ⍝ error: cons to atom 1 2│cons joy '3 2 dup - /' ⍝ error: divide by zero 3 0│/ joy '0 [y] [t] branch' ⍝ error: branch first arg must be bool 0 [y] [t]│branch joy 'true 0 <' ⍝ error: relational fn needs a number true 0│< joy '0 pred' ⍝ error: 0 has no predecessor 0│pred ⍝∇ joy nats display scripts._joy Back to: code Back to: Workspaces