[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: a brief introduction to "closures" for "uneducated" C hackers




For the record, you don't need the closure implementation technique to
include this form of procedure in your language. You can do it on a 
plain stack -- Matthias

   X-Authentication-Warning: fast.cs.utah.edu: majordom set sender to owner-plt-scheme@flux.cs.utah.edu using -f
   From: John David Stone <stone@cs.grinnell.edu>
   Date: Wed, 7 Feb 2001 15:35:02 -0600 (CST)
   Content-Type: text/plain; charset=us-ascii
   Reply-To: stone@cs.grinnell.edu
   Sender: owner-plt-scheme@fast.cs.utah.edu
   Precedence: bulk

   John Clonts writes:

    > I have a vague recollection that Pascal allowed nested functions-- but I
    > don't recall how or if it dealt with this.  Does anyone here know?

	   In Standard Pascal, you can't return a function from another
   function, but you can pass one in as a parameter to a function, so the
   problem does arise in that direction.  The solution was indeed to use a
   closure.  The Turbo Pascal implementers never got the hang of this, which
   is why their mechanism for passing procedures and functions as arguments is
   non-standard -- they used the pointer-passing technique that Matthias was
   ridiculing.

	   This property of Pascal was exploited, for instance, in
   R. D. Tennent's _Principles of programming languages_ (Englewood Cliffs,
   New Jersey: Prentice/Hall International, 1981), to construct classes.  He
   gives only a schematic example (see pages 143-144), but here's a complete
   Pascal program that demonstrates the technique:

   program demo (output);
   var i: integer;

     procedure random(seed: integer;
		      procedure inner(procedure draw(var x: real)));
       const m = 25173;
       const d = 65536;
       const i = 13849;
       var a: integer;

       procedure draw (var x: real);
       begin
	 a := (a*m + i) mod d;
	 x := a/d;
       end;

     begin {procedure random}
       a := seed mod d;
       inner(draw)  {The value passed here is a closure
		     that includes the binding for a.}
     end;

     procedure use(procedure draw(var x: real));
       var r: real;

     begin {procedure use}
       draw(r);  {update r to the next random number}
       writeln('After one draw, r = ', r:1:4);
       draw(r);
       writeln('After another draw, r = ', r:1:4)
     end;

   begin {program demo}
     random(389, use);  {create an object of the random-number generator class}
     random(471, use)   {create another}
   end.