~ Compares two values and returns True if they differ. ``` Print != 1 2; Print != 1 1; ``` ~ Def != as ( Not == ); ~ Discard the top stack item. ``` Print Drop "foo" "bar"; ``` ~ Def Drop as ( Let X ); ~ Swaps the top two stack items. ``` Print Swap 1 2; ``` ~ Def Swap as ( Let X ; Let Y ; Y X ); ~ Execute a block. ``` Do ( Print "hello world!" ); ``` ~ Def Do as ( Def F ; F ); ~ Takes a parameter of any type and returns True ``` Print Any? 12; Print Any? "hello"; Print Any? List (1 2 3); ``` ~ Def Any? ( True Drop ); ~ Duplicate the top stack item. ``` Def Square as (* Twin); Print Square 8; ``` ~ Def Twin as (Let X ; X X); ~ Triplicates the top stack item ``` Def Cube as (* * Triplet); Print Cube 8; ``` ~ Def Triplet as (Twin ; Twin); ~ Takes a boolean (`Cond`) and a block (`F`) as parameters. Executes `F`, given `Cond` is True. ``` When True ( Print "hello!" ); When False ( Print "bye!" ); ``` ~ Def When as ( Let Cond; Def F; Do If Cond then ( F ) else (); ); ~ Opposite of `When`. Takes a boolean (`Cond`) and a block (`F`) as parameters. Executes `F`, given `Cond` is False. ``` Unless True ( Print "hello!" ); Unless False ( Print "bye!" ); ``` ~ Def Unless as ( Let Cond; Def F; Do If Cond then ( ) else ( F ); ); ~ Takes two block parameters (`Cond` and `F`). Continually execute `F` while `Cond` evaluates to True. ``` While (True) ( Print "This will print forever..." ); While (False) ( Print "This won't print at all..." ); ``` ~ Def While ( Def Cond; Def F; Let Result be Cond; When Result then ( F ; While (Cond) (F) ) ); ~ Opposite of While. Takes two block parameters (`Cond` and `F`). Continually execute `F` until `Cond` evaluates to True. ``` Until (False) ( Print "This will print forever..." ); Until (True) ( Print "This won't print at all..." ); ``` ~ Def Until ( Def Cond; Def F; Let Result be Cond; Unless Result then ( F ; Until (Cond) (F) ); ); ~ Takes a number (`N`) and a block (`F`) as parameters. Evaluates `F` `N` times. ``` Times 3 ( Print "Hip Hip Hooray!" ); ``` ~ Def Times ( Let N be Of (Integer?); Def F; Unless Zero? N ( F ; Times - 1 N (F) ); ); ~ Takes symbol parameter `Mode`, string parameter `Filename` and block parameter `Body`. Opens the file `Filename` in mode `Mode`. Evaluates `Body`, passing it a reference to the file. ``` With \read "foo.txt" ( Let F be the file handle; Print Read-file F; ); ``` ~ ~Def With ( Let Mode be Of (Symbol?); Let Filename be Of (String?); Def Body; Let Fp be Open as Mode Filename; Body Fp; Close Fp );~ ~ Returns the list parameter reversed. ``` Print Reverse List (1 2 3); ``` ~ Def Reverse ( Def Reverse-helper ( Let L1 be List!; Let L2 be List!; Do If Empty? L2 ( L1 ) else ( Reverse-helper Push First L2 to L1 and Rest L2 ) ); Reverse-helper Empty; ) ~ Takes a block (`F`) and a list (`L`) as parameters. Applies a block to each element in a list ``` For each in Range 1 to 100 ( Print ); ``` ~ Def For ( ~~ Tail recursive; Let L be Of (List?); Def F; When Not Empty? L ( F First L; For each in Rest L do (F); ) ); ~ Takes a block (`F`), initial value (`I`), and list (`L`) as parameters. Applies `F` to each element in `L`, pushing `I` to the stack first. ``` Fold (*) from 1 over Range 1 to 10; Print; ``` ~ Def Fold ( Def F; Let I; Let L be Of (List?); I ; For each in L do (F); ); ~ Builds a string from a block parameter and prints it to standard output, without a newline. ``` Puts ( "The square of 10 is " * Twin 10 "\n"); ``` ~ Def Puts ( Put Fold ( Join Show ) from "" over Reverse List); ~ Builds a string from a block parameter and prints it to standard output, with a newline. ``` Puts ( "The square of 10 is " * Twin 10); ``` ~ Def Prints ( Print Fold ( Join Show ) from "" over Reverse List); ~ Takes a block parameter `Predicate` and a list `L`. Applies `Predicate` to each element in `L`. Returns a list containing only the elements where `Predicate` evaluated to True. ``` Def Even? as (Zero? Modulo 2); Filter (Even?) over Range 1 to 100; Print; ``` ~ Def Filter ( Def Predicate; Def Filter-helper ( Let Acc be List!; Let L be List!; Do If Empty? L ( Acc ) else ( Let R be Boolean! Predicate First L; Do If R ( Filter-helper Push First L to Acc and Rest L ) else ( Filter-helper Acc and Rest L ); ) ); Reverse Filter-helper Empty; ); ~ Takes two number parameters and returns the smaller one. ``` Print Min 3 10; ``` ~ Def Min as ( Let A be Of (Number?); Let B be Of (Number?); If < A B then B else A; ); ~ Takes two number parameters and returns the larger one. ``` Print Max 3 10; ``` ~ Def Max as ( Let A be Of (Number?); Let B be Of (Number?); If < A B then A else B; ); ~ Takes a predicate block (`F`) and a list (`L`) as parameters. Builds a new list by taking elements one by one from `L` and evaluating `F` on them. Stops building the list when the `F` first evaluates to False. ``` Print Take-while (< 10) Range 1 to 100; ``` ~ Def Take-while ( Def F; Let L be Of (List?); Def H as ( Let L; Unless Empty? L ( Let I be First L; Let R be F of I; When R then ( Push I; H Rest L ) ) ); Reverse H L Empty; ); ~ Takes a predicate block (`F`) and list (`L`) as parameters. Applies `F` to each element of `L`, returning True if `F` returned True every time, else returning False. ``` Print All (< 100) Range 1 to 10; Print All (< 10) Range 1 to 100; ``` ~ Def All ( Def F; Let L be Of (List?); Do If Empty? L then ( True ) else ( Do If F on First L then ( All (F) of Rest of L ) else ( False ) ) ); ~ Takes a predicate block and list as parameters. Returns True if evaluating the predicate on all of the list elements gives False, else returns False. ``` Print None (> 100) Range 1 to 10; Print None (> 10) Range 1 to 100; ``` ~ Def None ( Def P; Let L; All ( Not P ) of L; ); ~ Takes two list parameters and returns a new list created by joining the first list onto the end of the second list. ``` Print Append List (4 5 6) to List (1 2 3); ``` ~ Def Append ( Let L2; Let L1; L2; For each in Reverse L1 ( Push; ) ); ~ Takes two list parameters and returns a new list created by joining the second list onto the end of the first list. ``` Print Prepend List (1 2 3) to List (4 5 6); ``` ~ Def Prepend ( Swap ; Append ); ~ Takes a predicate block `Pred` and two other blocks `If-true` and `If-false`. Returns a block that takes one parameter (`X`) and applies the predicate to it. If this gives True then `If-true` is evaluated with `X` as a parameter. If not `If-false` is evaluated with `X` as a parameter. ``` Def Multiple as ( Zero? Modulo ); Def Fizzbuzz Case (Multiple of 15) then ( "Fizzbuzz" Drop ) Case (Multiple of 3) then ( "Fizz" Drop ) Case (Multiple of 5) then ( "Buzz" Drop ) else ( just return the number ); ``` For each in Range 1 to 100 ( Print Fizzbuzz ) ~ Def Case as ( Def Pred; Def If-true; Def If-false; ( Let X; Let B be Pred X; Do If B then (If-true X) else (If-false X) ); ); ~ Takes a list of numbers as a parameter and returns a list containing the same numbers in ascending order. ``` Print Sort List ( 9 6 2 5 7 4 1 3 8); ``` ~ Def Sort Case (Empty?) () else ( Let L; Let Pivot be First of L; Sort Filter (< Pivot) L; Sort Filter (>= Pivot) Rest of L; Push Pivot; Append ); ~ Takes a block (`F`) and a list (`L`) as parameters. Creates a new list where each element is the result of applying `F` to the corresponding element in `L`. ``` Def Square as (* Twin); Map (Square) over the Range from 1 to 10; Print ``` ~ Def Map ( Def F; Def Map-helper ( Let Acc be List!; Let L be List!; Do If Empty? L ( Acc ) else ( Let R be F of First L; Map-helper Push R to Acc and Rest L ) ); Reverse Map-helper Empty; ); ~ Takes an integer (`N`) and a list (`L`) as parameters. Returns a list created by removing the first `N` elements of `L`. ``` Print Discard 4 from Range 1 to 10; ``` ~ Def Discard ( Let N be Of (Integer?); Let L be Of (List?); Do If Zero? N ( L ) else ( When Empty? L ( Error "Cannot Discard more elements than in list" ); Discard - 1 N from Rest L ); ); ~ Takes an integer (`N`) and a list (`L`) as parameters. Returns a list containing only the first `N` elements of `L`. ``` Print Take 4 from Range 1 to 10; ``` ~ Def Take ( Def Take-helper ( Let Acc be List!; Let N be Number!; Let L be List!; Do If Zero? N ( Acc ) else ( When Empty? L ( Error "Cannot Take more elements than in list" ); Take-helper Push First L to Acc taking - 1 N from Rest L; ) ); Reverse Take-helper Empty; ); ~ Takes an integer (`N`) and a list or string (`L`) as parameters. Returns the `N`th element (indexed from zero) of `L`. ``` Print Index 4 of Range 0 to 100; ``` ~ Def Index ( Let N be Of (Integer?); Let L; When < 0 N ( Error Join "Invalid index " Show N ); When Empty? L ( Error "Index is beyond the end" ); Do If Zero? N ( return First element of L ) else ( Index - 1 N of Rest of L ); ); ~ Takes two number parameters (`Start` and `End`). Returns a list of numbers ranging from `Start` to `End` inclusive of `Start` but not `End` with a step of 1. ``` Print Range 1 to 100; ``` ~ Def Range ( Let Start be Number!; Let End be Number!; When > End Start ~~ TODO? maybe we could have this create a reverse range. ( Error Join Join Join "Invalid range " Show Start "..." Show End; ); Def Range-helper ( Let Start be Number!; Let End be Number!; Let L be List!; Do If < End Start ( Range-helper from + 1 Start to End with Push Start to L ) else ( L ); ); Reverse Range-helper from Start to End with Empty; ); ~ Takes a string (`Assertion`) and a boolean (`Result`). If `Result` is not True then throws an error, with the text of `Assertion` in the error message. ``` Assert "This assertion will pass" True; Assert "This assertion will fail" False; ``` ~ Def Assert ( Let Assertion be String!; Let Result be Boolean!; Unless Result ( Error Join Join "Failed assertion: '" Assertion "'" ); ); ~ Takes a block `Predicate` and a value `X`. Applies `Predicate` to `X`. If this returns False throw an error. If it returns True then return `X`; Def Print-integer ( Let I be Of (Integer?); Print I; ); ``` Print-integer 5; Print-integer 2.3; ``` ~ Def Of as ( Def Predicate; Let X; Let Result be Predicate X; Unless Result ( Error "Predicate failed" ); X; );