All pastes #753993 Raw Edit

Someone

public text v1 · immutable
#753993 ·published 2007-10-29 18:25 UTC
rendered paste body
{
	lazy list class
}

include "std.led";

class LazyList [X : equality];
var
	isEmpty : boolean;
	headFun : function()->X;
	tailFun : function()->LazyList[X];
	headDefined : boolean;
	tailDefined : boolean;

	function empty()->boolean;
	begin
		return isEmpty;
	end;

	function head()->X;
	var
		hd : X;
	begin
		hd := headFun();
		if ~ headDefined then begin
			headDefined := true;
			headFun := function()->X;
				begin
					return hd;
				end;
			end;
		return hd;
	end;

	function tail()->LazyList[X];
	var
		tl : LazyList[X];
	begin
		tl := tailFun();
		if ~ tailDefined then begin
			tailDefined := true;
			tailFun := function()->LazyList[X];
					begin
						return tl;
					end;
			end;
		return tl;
	end;
end;

function emptyList [X : equality] ()->LazyList[X];
begin
	return LazyList[X](
		true, NIL, NIL, false, false);
end;

function cons [X : equality] 
	(byName hd : X, byName tl : LazyList[X])->LazyList[X];
begin
	return LazyList[X](
		false,
		function()->X; begin return hd; end,
		function()->LazyList[X]; begin return tl; end,
		false, false);
end;

function map [X, Y : equality] 
	(transform : function(X)->Y, data : LazyList[X])->LazyList[Y];
begin
	if data.empty() then
		return emptyList[Y]()
	else
		return cons[Y](transform(data.head()), 
			map[X, Y](transform, data.tail()));
end;

function printFirstN [X : equality](aList : LazyList[X], n : integer);
var
	i : integer;
	theList : LazyList[X];
begin
	theList := aList;
	for i := 1 to n do
		if ~ theList.empty() then begin
			print(theList.head());
			print(" ");
			theList := theList.tail();
			end;
	print("\n");
end;

function iToj(i, j : integer)->LazyList[integer];
begin
	if i <= j then
		return cons[integer](i, iToj(i+1, j))
	else
		return emptyList[integer]();
end;

function oneToN(n : integer)->LazyList[integer];
begin
	return iToj(1, n);
end;

function reduce [X : equality, Y : object] (aList : LazyList[X], ident : Y,
	binFun: function(X, Y)->Y )->Y;
begin
	if aList.empty() then
		return ident
	else
		return binFun(aList.head(), 
			reduce[X, Y](aList.tail(), ident, binFun));
end;

function count [X : equality]
	(theList : LazyList[X], pred : function(X)->boolean)->integer;
begin
	return reduce[X, integer]
		(theList,
		0,
		function (ele : X, soFar : integer)->integer;
		begin
			if pred(ele) then
				return soFar + 1;
			return soFar;
		end);
end;

function isPrime(N : integer)->integer;
begin
	if 2 >= count[integer]
		(map[integer, integer](N.remainder, oneToN(N)), 0.equals)
	then
		return N
	else
		return 0;
end;

function filter [X : equality] 
	(aList : LazyList[X], pred : function(X)->boolean)->LazyList[X];
begin
	if aList.empty() then
		return aList;
	if pred(aList.head()) then
		return cons[X](aList.head(), filter[X](aList.tail(), pred))
	else
		return filter[X](aList.tail(), pred);
end;

function sieve(aList : LazyList[integer])->LazyList[integer];
const
	n := aList.head();

	function divides(x : integer)->boolean;
	begin
		return 0 <> x % n;
	end;
begin
	return cons[integer](n, sieve(filter[integer](aList.tail(), divides)));
end;

function expansion [X : equality] 
	(start : X, next : function(X)->X)->LazyList[X];
begin
	return cons[X](start, expansion[X](next(start), next));
end;

function abs (n : real)->real;
begin
	if n < 0.0 then
		return - n;
	return n;
end;

function converge (terms : LazyList[real], epsilon : real)->real;
var
	a, b : real;
begin
	a := terms.head();
	terms := terms.tail();
	b := terms.head();
	while abs(a - b) > epsilon do begin
		a := b;
		terms := terms.tail();
		b := terms.head();
		end;
	return b;
end;

function sqrt (n : real)->real;

	function nextTerm(x : real)->real;
	begin
		return (x + n / x) / 2.0;
	end;
begin
	return converge(expansion[real](n, nextTerm), 0.02);
end;

function cubeRoot (n : real)->real;

	function nextTerm(x : real)->real;
	begin
		return (x + n / (x * x)) / 2.0;
	end;
begin
	return converge(expansion[real](n, nextTerm), 0.02);
end;

function fibFrom (current : integer, next : function(integer)->integer) 
		->LazyList[integer];
const
	nextVal := next(current);
begin
	return cons[integer](nextVal, fibFrom(nextVal, current.plus));
end;

function merge[X : ordered] (first, second : LazyList[X])->LazyList[X];
begin
	if first.empty() then
		return second;
	if second.empty() then
		return first;

	while first.head() = second.head() do begin
		first := first.tail();
		if first.empty() then
			return second;
		end;

	if first.head() < second.head() then
		return cons[X](first.head(), merge[X](first.tail(), second))
	else
		return cons[X](second.head(), merge[X](first, second.tail()));
end;

var
	integers : LazyList[integer];
	evens : LazyList[integer];
	primes : LazyList[integer];
	primes2 : LazyList[integer];
	odds : LazyList[integer];
	fibs : LazyList[integer];

function hamming(data : LazyList[integer])->LazyList[integer];
const
	n := data.head();
begin
	return cons[integer](n, 
		hamming(
		merge[integer](data.tail(), 
			cons[integer](2 * n,
				cons[integer](3 * n,
					cons[integer](5 * n,
						emptyList[integer]()))))));
end;

begin
{	integers := cons[integer](1, map[integer, integer](1.plus, integers));
	printFirstN[integer] (integers, 26);

	evens := map[integer, integer](2.times, integers);
	printFirstN[integer] (evens, 6);

	primes := filter[integer](map[integer, integer](isPrime, integers),
			0.notEquals);
	printFirstN[integer](primes, 10);

	primes2 := sieve(integers.tail());

	printFirstN[integer](primes2, 10);

	odds := expansion[integer](1, 2.plus);
	printFirstN[integer](odds, 10);

	print("sqrt of 101.5 is " + sqrt(101.5) + "\n");
	print("cuberoot of 126.5 is " + cubeRoot(126.5) + "\n");

	fibs := fibFrom(0, 1.plus);
	printFirstN[integer](fibs, 5);}

	printFirstN[integer]
		(hamming(cons[integer](1, emptyList[integer]())), 100);
end;