67 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			OpenEdge ABL
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			OpenEdge ABL
		
	
	
	
	
	
{ $Header$ }
 | 
						|
 | 
						|
program ArrayWithoutArray(input, output);
 | 
						|
{	We simulate a (read-only) array by constructing a mapping
 | 
						|
	function   map(n)   which yields the n-th element.
 | 
						|
	We demonstrate its existence by first printing the length
 | 
						|
	of the array and then its contents.
 | 
						|
	This technique was first introduced by F.E.J. Kruseman-Aretz,
 | 
						|
	in the early sixties.
 | 
						|
}
 | 
						|
 | 
						|
procedure Action(n: integer; function map(n: integer): integer);
 | 
						|
	{	Action is called when the construction of the virtual
 | 
						|
		array is finished.  Actually, all elements now reside
 | 
						|
		on the stack.
 | 
						|
		n:	the length of the array,
 | 
						|
		map:	the mapping function.
 | 
						|
	}
 | 
						|
	var i: integer;
 | 
						|
	begin	{ show that the whole array is still there }
 | 
						|
		writeln('#elems:', n);
 | 
						|
		write('elems:');
 | 
						|
		for i:= 1 to n do
 | 
						|
			write(map(i))
 | 
						|
	end {Action};
 | 
						|
 | 
						|
procedure Construct(n: integer; function oldmap(n: integer): integer);
 | 
						|
	{	For each value read, Construct will store that value and
 | 
						|
		declare a new map function, composed of the old one
 | 
						|
		augmented by the new value.
 | 
						|
		It then calls itself recursively for the next value.
 | 
						|
		
 | 
						|
		n:	element number on this level
 | 
						|
		oldmap:	map for 1 .. n-1
 | 
						|
	}
 | 
						|
	var x: integer;		{ the value stored at level n }
 | 
						|
	
 | 
						|
	function newmap(i: integer): integer;
 | 
						|
		{ yields elements stored so far }
 | 
						|
		begin
 | 
						|
			if	{ the i-th element is kept on this level}
 | 
						|
				i = n
 | 
						|
			then	{ yield it }
 | 
						|
				newmap := x
 | 
						|
			else	{ try lower down the road }
 | 
						|
				newmap := oldmap(i)
 | 
						|
		end {newmap};
 | 
						|
	
 | 
						|
	begin
 | 
						|
		read(x);
 | 
						|
		if	{ it is a valid value }
 | 
						|
			x >= 0
 | 
						|
		then	{ we continue reading values and constructing maps }
 | 
						|
			Construct(n + 1, newmap)
 | 
						|
		else	{ we stop reading and pass the info on to Action }
 | 
						|
			Action(n - 1, newmap)
 | 
						|
	end {Construct};
 | 
						|
 | 
						|
function EmptyMap(n: integer): integer;
 | 
						|
	begin
 | 
						|
		writeln('Illegal index', n, '; 0 yielded.');
 | 
						|
		EmptyMap := 0
 | 
						|
	end {EmptyMap};
 | 
						|
 | 
						|
begin
 | 
						|
	Construct(1, EmptyMap)
 | 
						|
end.
 |