[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.