🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.eiffel
Article #1531

Re: Passing functions as parameters

#1531
From: Jos Warmer
Date: Mon, 05 Feb 1990 13:51
867 lines
24151 bytes
In article <120012@gore.com> jacob@gore.com (Jacob Gore) writes:
>/ comp.lang.eiffel / marcap@hercule.cs.concordia.ca (PAWLOWSKY) / Feb 2, 1990 /
>> A while back, the passing of functions as parameters was mentioned.  If
>> memory is correct (I don't have a list of comp.lang.eiffel postings, is 
>> someone out there keeping a ftp'able copy?) it ended up with someone
>> saying it is not needed since you can redefine the function as needed
>> in the class.
>
>I take this as confirmation that no, you can't pass functions as parameters
>in Eiffel.
>
>Could somebody tell me then what the inheritance-related trick is for
>supplying a list class with the following routines:
>
>    1.	apply-routine   -- like LISP's "mapcar": same operation repeatedly
>				applied to all elements of the list
>

This is the `pre_order' or `post_order' from MY_TREE.
See later on.

>    2.	insert-function -- like APL's "/":
>				given a list L such that nb_elements(L)>1
>				and a fuction F,
>					if L.nb_elements > 2 then
>						return F(L.first, L.rest)
>					else
>						return F(L.first, L.second)

This one is not in MY_TREE, but the insert-function could be done
in analogy with `pre_order' and `bpre_order'.

>
>The one particularly useful in Eiffel is a combination of 1 and 2:
>
>    3.	for-all		-- given a BOOLEAN function F and a list L,
>				return 'true' if F(L.i_th(k)) returns true
>				for all 1 <= k <= L.nb_elements
>
>And, of course, a there-exists function is analogous.

Both for-all and there-exists can easily be implemented by `bpre_order'
or `bpost_order' from MY_TREE.
See later on. In the example, there-exists is shown.

By the way, eiffel naming conventions would call `there-exists' `has'.

>
>Having such features in list classes would make writing assertions about
>lists much easier.
>
>Jacob
>--
>Jacob Gore		Jacob@Gore.Com			boulder!gore!jacob

Yes I can tell you what trick I use. My trick is implemented for tree's, but
the idea remains the same for sets, list and so on.
I desperately needed a way to traverse complete tree's and perform
an action on each node.
Because this kind of functionality is needed very often in lists, trees, sets
and so on, I see the absense as a serious omission in the library.


		    DESCRIPTION OF THE METHOD

Class MY_TREE is an adaption of class TWO_WAY_TREE from the library.
It adds several routines for traversing the tree and performing actions
on each node of the tree. The routine `pre_order' will be taken as
an example. The remaining routines are in the class text below.

    pre_order( a : TREE_ACTION[T] ) is
	-- Traverses the tree of which `Current' is the root in preorder
	-- and performs `a.action' on each node.
    require
	not a.Void

The routine `pre_order' takes as parameter an entity `a' of
type TREE_ACTION[T].
TREE_ACTION is a deferred class with one function called `action':

    deferred class TREE_ACTION[T] export
	action

    feature
	action(t : MY_TREE[T], level : INTEGER) is deferred end;

    end -- class TREE_ACTION

`pre_order' traverses the tree in preorder and performs a.action(node, level)
for each node in the tree.  Level is the depth of the node in the tree.

To use it, define a descendant of class TREE_ACTION and give an
implementation of `action'.  I will call such a class an action class.
For example, a class to count the number of nodes in a tree:

    class COUNT_ACTION[T] export
	   action, nr_nodes

    inherit
	   TREE_ACTION[T];

    feature
       nr_nodes : INTEGER;

       action( t : MY_TREE[T], level : INTEGER ) is
       do
	   nr_nodes := nr_nodes + 1;
       end;
    end;

Usage:
     ...
     count: COUNT_ACTION[SOME_TYPE];
     tree : MY_TREE     [SOME_TYPE];

     ... is
     do
	 count.Create;
	 tree.post_order(count);
	 io.putint( count.nr_nodes ); io.new_line;
     end;

Disadvantages:

- For each routine you want to apply, you need to write a separate
  action class. This might result in lots of little classes.

Advantages:

- You can apply different routines to the elements of a tree.
  The method with redefining a function within TWO_WAY_TREE only
  gives you one routine.

- All data associated with the routine that is applied to each node
  can be local to the action class.
  Remind that in e.g. C you always need global variables for usage
  by the routine.

- If you need to apply complex operations on each node, then the
  action class can incorporate all needed routines and variables.
  I use action classes which are over 200 lines long.

Advantages 2 and 3 give much better information hiding then in
conventional languages.

Following is a shar-archive, which contains the classes I use for this
kind of traversals, including an example program.
I have used them for almost a year, so they should be reliable.

By the way, how do we define `production quality' ?

				  Jos Warmer


: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'README'
sed 's/^X//' > 'README' << '+ END-OF-FILE ''README'
XREADME          : this file
XDESCRIPTION     : description of the method used, including (dis)advantages
X
XThe following four classes should reside in a library directory.
XThey implement all kinds of traversal for trees.
X
Xmy_tree.e	: adaption of two_way_tree with traversal routines
Xbtree_action.e  : deferred action's for traversing my_tree.
Xtraverse.e      : deferred action's for traversing my_tree.
Xtree_action.e   : deferred action's for traversing my_tree.
X
XThe following trhee classes show some examples using the library.
X
Xexample.e       : 'main' program
Xexists.e        : actual btree_action
Xprint_tree.e    : actual tree_action
+ END-OF-FILE README
chmod 'u=rw,g=rw,o=' 'README'
set `wc -c 'README'`
count=$1
case $count in
637)	:;;
*)	echo 'Bad character count in ''README' >&2
		echo 'Count should be 637' >&2
esac
echo Extracting 'DESCRIPTION'
sed 's/^X//' > 'DESCRIPTION' << '+ END-OF-FILE ''DESCRIPTION'
X
X
X		    DESCRIPTION OF THE METHOD
X
XClass MY_TREE is an adaption of class TWO_WAY_TREE from the library.
XIt adds several routines for traversing the tree and performing actions
Xon each node of the tree. The routine `pre_order' will be taken as
Xan example. The remaining routines are in the class text below.
X
X    pre_order( a : TREE_ACTION[T] ) is
X	-- Traverses the tree of which `Current' is the root in preorder
X	-- and performs `a.action' on each node.
X    require
X	not a.Void
X
XThe routine `pre_order' takes as parameter an entity `a' of
Xtype TREE_ACTION[T].
XTREE_ACTION is a deferred class with one function called `action':
X
X    deferred class TREE_ACTION[T] export
X	action
X
X    feature
X	action(t : MY_TREE[T], level : INTEGER) is deferred end;
X
X    end -- class TREE_ACTION
X
X`pre_order' traverses the tree in preorder and performs a.action(node, level)
Xfor each node in the tree.  Level is the depth of the node in the tree.
X
XTo use it, define a descendant of class TREE_ACTION and give an
Ximplementation of `action'.  I will call such a class an action class.
XFor example, a class to count the number of nodes in a tree:
X
X    class COUNT_ACTION[T] export
X	   action, nr_nodes
X
X    inherit
X	   TREE_ACTION[T];
X
X    feature
X       nr_nodes : INTEGER;
X
X       action( t : MY_TREE[T], level : INTEGER ) is
X       do
X	   nr_nodes := nr_nodes + 1;
X       end;
X    end;
X
XUsage:
X     ...
X     count: COUNT_ACTION[SOME_TYPE];
X     tree : MY_TREE     [SOME_TYPE];
X
X     ... is
X     do
X	 count.Create;
X	 tree.post_order(count);
X	 io.putint( count.nr_nodes ); io.new_line;
X     end;
X
XDisadvantages:
X
X- For each routine you want to apply, you need to write a separate
X  action class. This might result in lots of little classes.
X
XAdvantages:
X
X- You can apply different routines to the elements of a tree.
X  The method with redefining a function within TWO_WAY_TREE only
X  gives you one routine.
X
X- All data associated with the routine that is applied to each node
X  can be local to the action class.
X  Remind that in e.g. C you always need global variables for usage
X  by the routine.
X
X- If you need to apply complex operations on each node, then the
X  action class can incorporate all needed routines and variables.
X  I use action classes which are over 200 lines long.
X
XAdvantages 2 and 3 give much better information hiding then in
Xconventional languages.
X
XI have used them for almost a year, so they should be reliable.
X
XBy the way, how do we define `production quality' ?
X
X				  Jos Warmer
+ END-OF-FILE DESCRIPTION
chmod 'u=rw,g=rw,o=' 'DESCRIPTION'
set `wc -c 'DESCRIPTION'`
count=$1
case $count in
2488)	:;;
*)	echo 'Bad character count in ''DESCRIPTION' >&2
		echo 'Count should be 2488' >&2
esac
echo Extracting 'btree_action.e'
sed 's/^X//' > 'btree_action.e' << '+ END-OF-FILE ''btree_action.e'
X--  Function to apply during tree-traversal.
X--  See MY_TREE.
X--
X--  To use it, inherit from this class and define an implementation
X--  for `action'.
X
X--  Author      :  Jos Warmer , e-mail: jos@cs.vu.nl
X--  Organisation:  Department of Mathematics and Computer Science
X--      	   Vrije Universiteit Amsterdam
X--  Version     :  5 Februari 1990
X
Xdeferred class BTREE_ACTION[T] export
X
X    action
X
Xfeature
X
X    action(t : MY_TREE[T], level : INTEGER) : BOOLEAN is deferred end;
X
Xend -- class BTREE_ACTION
+ END-OF-FILE btree_action.e
chmod 'u=rw,g=r,o=' 'btree_action.e'
set `wc -c 'btree_action.e'`
count=$1
case $count in
506)	:;;
*)	echo 'Bad character count in ''btree_action.e' >&2
		echo 'Count should be 506' >&2
esac
echo Extracting 'count_action.e'
sed 's/^X//' > 'count_action.e' << '+ END-OF-FILE ''count_action.e'
X-- count all nodes in a tree
X
Xclass COUNT_ACTION[T] export
X
X       action, nr_nodes
X
Xinherit
X       TREE_ACTION[T];
X
Xfeature
X   nr_nodes : INTEGER;
X
X   action( t : MY_TREE[T], level : INTEGER ) is
X   do
X       nr_nodes := nr_nodes + 1;
X   end;
Xend;
+ END-OF-FILE count_action.e
chmod 'u=rw,g=rw,o=' 'count_action.e'
set `wc -c 'count_action.e'`
count=$1
case $count in
249)	:;;
*)	echo 'Bad character count in ''count_action.e' >&2
		echo 'Count should be 249' >&2
esac
echo Extracting 'example.e'
sed 's/^X//' > 'example.e' << '+ END-OF-FILE ''example.e'
Xclass EXAMPLE export
X
X    -- This class is ment to show the usage of the traverse routines in
X    -- MY_TREE.
X
Xfeature
X    tree : MY_TREE[STRING];
X
X    Create is
X    local
X	tree_printer : PRINT_TREE;
X	count        : COUNT_ACTION[STRING];
X    do
X	fill_tree;
X
X	tree_printer.Create("pre_order");
X	tree.pre_order(tree_printer);
X	tree_printer.close;
X
X	tree_printer.Create("post_order");
X	tree.post_order(tree_printer);
X	tree_printer.close;
X	
X	count.Create;
X	tree.post_order(count);
X	io.putint(count.nr_nodes); io.putstring(" nodes\n"); 
X	if there_exists("four") then
X	    io.putstring("four exists"); io.new_line;
X	else
X	    io.putstring("four exists not"); io.new_line;
X	end;
X	if there_exists("2") then
X	    io.putstring("2 exists"); io.new_line;
X	else
X	    io.putstring("2 exists not"); io.new_line;
X	end;
X    end;
X
X    fill_tree is
X	-- Put some strings in the `tree'.
X    local
X	tmp : MY_TREE[STRING];
X    do
X	tree.Create("root");
X	tree.child_put_right("three");
X	tree.child_put_right("two");
X	tree.child_put_right("one");
X
X	tree.child_start;
X	tmp := tree.child;
X	tmp.child_put_right("c");
X	tmp.child_put_right("b");
X	tmp.child_put_right("a");
X
X	tree.child_start;
X	tree.child_forth;
X	tree.child_forth;
X	tmp := tree.child;
X	tmp.child_put_right("3");
X	tmp.child_put_right("2");
X	tmp.child_put_right("1");
X    end;
X
X    there_exists( s : STRING ) : BOOLEAN is
X	-- Is string `s' part of the `tree' ?
X    local
X	exists : EXISTS [STRING];
X	tmp    : MY_TREE[STRING];
X    do
X        exists.Create(s);
X	tmp := tree.bpre_order(exists);
X	Result := not tmp.Void;
X    end;
X
Xend;
+ END-OF-FILE example.e
chmod 'u=rw,g=rw,o=' 'example.e'
set `wc -c 'example.e'`
count=$1
case $count in
1564)	:;;
*)	echo 'Bad character count in ''example.e' >&2
		echo 'Count should be 1564' >&2
esac
echo Extracting 'exists.e'
sed 's/^X//' > 'exists.e' << '+ END-OF-FILE ''exists.e'
Xclass EXISTS [T->COMPARABLE] export
X
X    action
X
Xinherit
X	BTREE_ACTION[T]
Xfeature
X
X    item : T;
X
X    Create( s : T ) is
X    do
X	item := s;
X    end;
X
X    action( node : MY_TREE[T] ; level : INTEGER ) : BOOLEAN is
X    do
X	Result := not (item >= node.item and item <= node.item);
X    end;
X
Xend;
X
X
+ END-OF-FILE exists.e
chmod 'u=rw,g=rw,o=' 'exists.e'
set `wc -c 'exists.e'`
count=$1
case $count in
295)	:;;
*)	echo 'Bad character count in ''exists.e' >&2
		echo 'Count should be 295' >&2
esac
echo Extracting 'my_tree.e'
sed 's/^X//' > 'my_tree.e' << '+ END-OF-FILE ''my_tree.e'
X--  This is a descendant of TWO_WAY_TREE, with routines added for
X--  traversing the tree and performing actions on each node.
X
X--  Author      :  Jos Warmer , e-mail: jos@cs.vu.nl
X--  Organisation:  Department of Mathematics and Computer Science
X--      	   Vrije Universiteit Amsterdam
X--  Version     :  5 Februari 1990
X
Xclass MY_TREE[T] export
X	repeat TWO_WAY_TREE,
X
X	    -- various traverse routines for
X	    -- complete tree or until boolean function returns false
X
X	post_order, pre_order, bpost_order, bpre_order,
X	traverse, search_pre,
X
X	    -- internal routines
X	do_post_order {MY_TREE}, do_pre_order {MY_TREE},
X	do_bpost_order {MY_TREE}, do_bpre_order {MY_TREE},
X	do_traverse { MY_TREE}
X
Xinherit
X	TWO_WAY_TREE [T] 
X		rename
X			Create as tree_create
X		redefine
X			parent, search_child
Xfeature
X	
X    parent: MY_TREE [T];		 -- Used as anchor.
X	
X    Create( v : T ) is
X	--  Just a copy of the TWO_WAY_TREE Create routine.
X    do
X	tree_create(v);
X    end;
X
X    search_pre( a : BTREE_ACTION[T] ) : like parent is
X	-- Traverses the tree after `Current' and performs `a.action'
X	-- on each node.
X	-- Stops when `a.action' returns FALSE and returns the
X	-- node on which FALSE was returned.
X	-- Returns Void when `a.action' returns FALSE nowhere.
X	-- Keeps on traversing at parent.
X    require
X	not a.Void
X    local
X	x : like parent;
X    do
X	from  x := right_sibling
X	until x.Void or not Result.Void
X	loop
X	    Result := x.bpre_order(a);
X	    x := x.right_sibling;
X	end;
X	if Result.Void and not parent.Void then
X	    Result := parent.search_pre(a);
X	end;
X    end;
X
X    bpre_order( a : BTREE_ACTION[T] ) : like parent  is
X	-- Traverses the tree of which `Current' is the root in preorder
X	-- and performs `a.action' on each node.
X	-- Stops when `a.action' returns FALSE and returns the
X	-- node on which false was returned.
X	-- Returns Void when `a.action' returns FALSE nowhere.
X    require
X	not a.Void
X    do
X	--  extra routine to supply level
X	Result := do_bpre_order(a, 0);
X    end;
X
X    do_bpre_order(a : BTREE_ACTION[T],level : INTEGER) : like parent is
X	-- This is the working routine for bpre_order.
X    local
X	tmp : like parent;
X    do
X	if not a.action(Current, level) then
X	    Result := Current;
X	else
X	    from  tmp := first_child
X	    until tmp.Void or not Result.Void
X	    loop
X		Result := tmp.do_bpre_order(a, level+1);
X		tmp    := tmp.right_sibling
X	    end;
X	end;
X    end;
X
X    bpost_order( a : BTREE_ACTION[T] ) : like parent  is
X	-- Traverses the tree of which `Current' is the root in postorder
X	-- and performs `a.action' on each node.
X	-- Stops when `a.action' returns FALSE and returns the
X	-- node on which false was returned.
X	-- Returns Void when `a.action' returns FALSE nowhere.
X    require
X	not a.Void
X    do
X	--  extra routine to supply level
X	Result := do_bpost_order(a, 0);
X    end;
X
X    do_bpost_order(a : BTREE_ACTION[T],level : INTEGER): like parent is
X	-- This is the working routine for bpost_order.
X    local
X	tmp : like parent;
X    do
X	from  tmp := first_child
X	until tmp.Void or not Result.Void
X	loop
X	    Result := tmp.do_bpost_order(a, level+1);
X	    tmp    := tmp.right_sibling
X	end;
X
X	if not a.action(Current, level) then
X	    Result := Current;
X	end;
X    end;
X
X    post_order( a : TREE_ACTION[T] ) is
X	-- Traverses the tree of which `Current' is the root in postorder
X	-- and performs `a.action' on each node.
X    require
X	not a.Void
X    do
X	--  extra routine to supply level
X	do_post_order(a, 0);
X    end;
X
X    do_post_order( a : TREE_ACTION[T], level : INTEGER ) is
X	-- This is the working routine for post_order.
X    local
X	tmp : like parent;
X    do
X	from  tmp := first_child
X	until tmp.Void
X	loop
X	    tmp.do_post_order(a, level+1);
X	    tmp := tmp.right_sibling
X	end;
X
X	a.action(Current, level);
X    end;
X
X    traverse( action : TRAVERSE[T] ) is
X	-- Traverses the tree of which `Current' is the root.
X	-- On each node, a.enter is called first,
X	-- then the children are traversed,
X	-- and after that a.leave is called.
X	--
X	-- This combines pre- and post-order traversal:
X	-- If a.enter is empty, this is the same as post_order.
X	-- If a.leave is empty, this is the same as pre_order.
X    do
X	do_traverse(action, 0);
X    end;
X
X    do_traverse( action : TRAVERSE[T], level : INTEGER ) is
X	-- This is the working routine for traverse.
X    local
X	tmp : like parent;
X    do
X	action.enter(Current, level);
X
X	from  tmp := first_child
X	until tmp.Void
X	loop
X	    tmp.do_traverse(action, level+1);
X	    tmp := tmp.right_sibling
X	end;
X
X	action.leave(Current, level);
X    end;
X
X    pre_order( a : TREE_ACTION[T] ) is
X	-- Traverses the tree of which `Current' is the root in preorder
X	-- and performs `a.action' on each node.
X    require
X	not a.Void
X    do
X	--  extra routine to supply level
X	do_pre_order(a, 0);
X    end;
X
X    do_pre_order( a : TREE_ACTION[T], level : INTEGER ) is
X	-- This is the working routine for do_pre_order.
X    local
X	tmp : like parent;
X    do
X	a.action(Current, level);
X
X	from  tmp := first_child
X	until tmp.Void
X	loop
X	    tmp.do_pre_order(a, level+1);
X	    tmp := tmp.right_sibling
X	end;
X    end;
X
X    search_child (sought: like parent; i: INTEGER) is
X	-- Move cursor under `i'-th occurence of `sought' if
X	-- exists among children; go child_offright if none.
X	--
X	-- NOTE: This is the correct version of `search_child'.
X	--       The version in the library is incorrect.
X    require
X	arguments_not_void: not sought.Void
X    local
X	j: INTEGER
X    do
X	-- child_mark;      -- COMMENTED OUT: this was in the library
X	from
X	    go_offleft
X	invariant
X	    child_position >= 0
X	variant
X	    arity - child_position
X	until
X	    child_offright or else (j = i)
X	loop
X	    child_forth;
X	    if (sought = child) then
X		j := j + 1
X	    end -- if
X	end;
X	-- child_return      -- COMMENTED OUT: this was in the library
X			     -- Using `child_mark' at the entrance and
X			     -- `child_return' at the end, will NEVER
X			     -- move the cursor.
X    end; -- search_child
X
Xend -- class MY_TREE
+ END-OF-FILE my_tree.e
chmod 'u=rw,g=r,o=' 'my_tree.e'
set `wc -c 'my_tree.e'`
count=$1
case $count in
5943)	:;;
*)	echo 'Bad character count in ''my_tree.e' >&2
		echo 'Count should be 5943' >&2
esac
echo Extracting 'print_tree.e'
sed 's/^X//' > 'print_tree.e' << '+ END-OF-FILE ''print_tree.e'
XClass PRINT_TREE export
X
X    action, close
X
Xinherit
X	TREE_ACTION[STRING]
Xfeature
X
X    Tablength : STRING is "    ";
X    file      : FILE;
X
X    Create( file_name : STRING ) is
X    do
X	file.Create(file_name);
X	file.open_write;
X    end;
X
X    action( node : MY_TREE[STRING] ; level : INTEGER ) is
X	-- Print `node', with `level' tabs indentation on `file'.
X    local
X	i : INTEGER;
X    do
X        from  i := 0
X	until i = level
X	loop
X	    file.putstring(Tablength);
X	    i := i + 1;
X	end;
X	file.putstring(node.item); file.new_line;
X    end;
X
X    close is
X    do
X	file.close;
X    end;
X
Xend;
+ END-OF-FILE print_tree.e
chmod 'u=rw,g=rw,o=' 'print_tree.e'
set `wc -c 'print_tree.e'`
count=$1
case $count in
583)	:;;
*)	echo 'Bad character count in ''print_tree.e' >&2
		echo 'Count should be 583' >&2
esac
echo Extracting 'traverse.e'
sed 's/^X//' > 'traverse.e' << '+ END-OF-FILE ''traverse.e'
X--  Functions to apply during tree-traversal.
X--  See MY_TREE.
X--
X--  To use it, inherit from this class and define an implementation
X--  for `enter' and `leave'.
X
X--  Author      :  Jos Warmer , e-mail: jos@cs.vu.nl
X--  Organisation:  Department of Mathematics and Computer Science
X--      	   Vrije Universiteit Amsterdam
X--  Version     :  5 Februari 1990
X
Xdeferred class TRAVERSE[T] export
X
X    enter, leave
X
Xfeature
X
X    enter( node : MY_TREE[T]; level : INTEGER ) is
X	--  Called at entering the node, before the children are
X	--  visited.
X    require
X	not node.Void;
X	level >= 0;
X    deferred
X    end;
X
X    leave( node : MY_TREE[T]; level : INTEGER ) is
X	--  Called at leaving the node, after the children are
X	--  visited.
X    require
X	not node.Void;
X	level >= 0;
X    deferred
X    end;
X
Xend;
+ END-OF-FILE traverse.e
chmod 'u=rw,g=r,o=' 'traverse.e'
set `wc -c 'traverse.e'`
count=$1
case $count in
799)	:;;
*)	echo 'Bad character count in ''traverse.e' >&2
		echo 'Count should be 799' >&2
esac
echo Extracting 'tree_action.e'
sed 's/^X//' > 'tree_action.e' << '+ END-OF-FILE ''tree_action.e'
X--  Function to apply during tree-traversal.
X--  See MY_TREE.
X--
X--  To use it, inherit from this class and define an implementation
X--  for `action'.
X
X--  Author      :  Jos Warmer , e-mail: jos@cs.vu.nl
X--  Organisation:  Department of Mathematics and Computer Science
X--      	   Vrije Universiteit Amsterdam
X--  Version     :  5 Februari 1990
X
Xdeferred class TREE_ACTION[T] export
X
X    action
X
Xfeature
X
X    action(t : MY_TREE[T], level : INTEGER) is deferred end;
X
Xend -- class TREE_ACTION
+ END-OF-FILE tree_action.e
chmod 'u=rw,g=r,o=' 'tree_action.e'
set `wc -c 'tree_action.e'`
count=$1
case $count in
494)	:;;
*)	echo 'Bad character count in ''tree_action.e' >&2
		echo 'Count should be 494' >&2
esac
echo Extracting '.eiffel'
sed 's/^X//' > '.eiffel' << '+ END-OF-FILE ''.eiffel'
XROOT: example
XUNIVERSE: 
X          /usr/local/eiffel/Eiffel/library/support
X	  /usr/local/eiffel/Eiffel/library/structures
XEXTERNAL:
XNO_ASSERTION_CHECK (N):
XPRECONDITIONS (Y): ALL
XALL_ASSERTIONS (N):
XDEBUG (N):
XTRACE (N):
XOPTIMIZE (N):
XGARBAGE_COLLECTION (Y)
XC_PACKAGE (N):
XC_EXTERNAL:
XMAKE:
XVISIBLE (N):
+ END-OF-FILE .eiffel
chmod 'u=rwx,g=rx,o=' '.eiffel'
set `wc -c '.eiffel'`
count=$1
case $count in
305)	:;;
*)	echo 'Bad character count in ''.eiffel' >&2
		echo 'Count should be 305' >&2
esac
exit 0
--
                                 Jos Warmer
				 jos@cs.vu.nl
				 ...uunet!mcvax!cs.vu.nl!jos
Technical Details
Message-ID: <5287@star.cs.vu.nl>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!hp4nl!star.cs.vu.nl!jos
References: <1832@clyde.concordia.ca> <120012@gore.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!hp4nl!star.cs.vu.nl!jos
From: jos@cs.vu.nl (Jos Warmer)
Newsgroups: comp.lang.eiffel
Subject: Re: Passing functions as parameters
Message-ID: <5287@star.cs.vu.nl>
Date: 5 Feb 90 13:51:32 GMT
References: <1832@clyde.concordia.ca> <120012@gore.com>
Sender: news@cs.vu.nl
Organization: Fac. Wiskunde & Informatica, VU, Amsterdam
Lines: 867