Prelude

Drop

Discard the top stack item.

Print Drop "foo" "bar";
Source
Def Drop as ( Let X );

Swap

Swaps the top two stack items.

Print Swap 1 2;
Source
Def Swap as ( Let X ; Let Y ; Y X );

Do

Execute a block.

Do ( Print "hello world!" );
Source
Def Do as ( Def F ; F );

Any?

Takes a parameter of any type and returns True

Print Any? 12;
Print Any? "hello";
Print Any? List (1 2 3);
Source
Def Any? ( True Drop );

Twin

Duplicate the top stack item.

Def Square as (* Twin);
Print Square 8;
Source
Def Twin as (Let X ; X X);

Triplet

Triplicates the top stack item

Def Cube as (* * Triplet);
Print Cube 8;
Source
Def Triplet as (Twin ; Twin);

When

Takes a boolean (Cond) and a block (F) as parameters. Executes F, given Cond is True.

When True ( Print "hello!" );
When False ( Print "bye!" );
Source
Def When as (
	Let Cond;
	Def F;
	Do If Cond then ( F ) else ();
);

Unless

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!" );
Source
Def Unless as (
	Let Cond;
	Def F;
	Do If Cond then ( ) else ( F );
);

While

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..." );
Source
Def While (
	Def Cond;
	Def F;
	Let Result be Cond;
	When Result then ( F ; While (Cond) (F) )
);

Until

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..." );
Source
Def Until (
	Def Cond;
	Def F;
	Let Result be Cond;
	Unless Result then ( F ; Until (Cond) (F) );
);

Times

Takes a number (N) and a block (F) as parameters. Evaluates F N times.

Times 3 ( Print "Hip Hip Hooray!" );
Source
Def Times (
	Let N be Of (Integer?);
	Def F;
	Unless Zero? N ( F ; Times - 1 N (F) );
);

With

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;
);
Source
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
);

Reverse

Returns the list parameter reversed.

Print Reverse List (1 2 3);
Source
Def Reverse (
	Fold ( Push ) from Empty over List!;
);

For

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 );
Source
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);
	)
);

Fold

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;
Source
Def Fold (
	Def F;
	Let I;
	Let L be Of (List?);
	I ; For each in L do (F);
);

Puts

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");
Source
Def Puts ( Put Fold ( Join Show ) from "" over Reverse List);

Prints

Builds a string from a block parameter and prints it to standard output, with a newline.

Puts ( "The square of 10 is " * Twin 10);
Source
Def Prints ( Print Fold ( Join Show ) from "" over Reverse List);

Filter

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;
Source
Def Filter (
	Def Predicate;
	Let L be Of (List?);
   Empty;
	For each in L (
		Let I;
		Let R be Predicate I;
		When R ( Push I );
	);
	Reverse;
);

Min

Takes two number parameters and returns the smaller one.

Print Min 3 10;
Source
Def Min as (
	Let A be Of (Number?);
	Let B be Of (Number?);
	If < A B then B else A;
);

Max

Takes two number parameters and returns the larger one.

Print Max 3 10;
Source
Def Max as (
	Let A be Of (Number?);
	Let B be Of (Number?);
	If < A B then A else B;
);

Take-while

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;
Source
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;
);

All

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;
Source
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 )
	)
);

None

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;
Source
Def None (
	Def P;
	Let L;
	All ( Not P ) of L;
);

Append

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);
Source
Def Append (
	Let L2;
	Let L1;
	L2;
	For each in Reverse L1 (
		Push;
	)
);

Prepend

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);
Source
Def Prepend ( Swap ; Append );

Case

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 )

Source
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)
	);
);

Sort

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);
Source
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
	);

Map

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
Source
Def Map (
	Def F;
	Let L be a List!;

	Do If Empty? L ( L )
	else (
		Let X be First of L;
		Let Res be F X;

		return Push Res to Map (F) over Rest of L;
	);
);

Discard

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;
Source
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
	);
);

Take

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;
Source
Def Take (
	Let N be Of (Integer?);
	Let L be Of (List?);

	Do If Zero? N ( Empty list ) else (
		When Empty? L ( Error "Cannot Take more elements than in list" );
		Push First L to Take - 1 N from Rest of L
	);
);

Index

Takes an integer (N) and a list (L) as parameters. Returns the Nth element (indexed from zero) of L.

Print Index 4 of Range 0 to 100;
Source
Def Index (
	Let N be Of (Integer?);
	Let L be List!;

	When < 0 N ( Error Join "Invalid index " Show N );

	Do If Zero? N ( return First element of L )
	else (
		When Empty? L ( Error "Index is beyond end of list" );
		Index - 1 N of Rest of L
	);
);

Range

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;
Source
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;
	);

	Reverse List (
		Start;
		While (Triplet ; < End) ( + 1 );
		Drop; Drop;
	)
);

Assert

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;
Source
Def Assert (
	Let Assertion be String!;
	Let Result be Boolean!;

	Unless Result ( Error Join Join "Failed assertion: '" Assertion "'" );
);