comp.lang.ada
 help / color / mirror / Atom feed
From: ncohen@watson.ibm.com (Norman H. Cohen)
Subject: Re: Q: access to subprogram
Date: 1996/07/08
Date: 1996-07-08T00:00:00+00:00	[thread overview]
Message-ID: <4rre7j$pv7@watnews1.watson.ibm.com> (raw)
In-Reply-To: Du4tvx.13s@world.std.com


In article <Du4tvx.13s@world.std.com>, bobduff@world.std.com (Robert A Duff)
writes: 

|> Ignore efficiency and implementation difficulty, for the moment.  Show
|> me an example or two illustrating the tremendous expressive power, using
|> some imagined syntax for expressing full closures.  (I know there's some
|> expressive power there, but it's not clear to me how tremendous it is.
|> I'm wondering if I've just not had enough experience in Lisp, etc.  I've
|> done some Lisp programming, and used closures, but don't miss them *all*
|> that much in Ada-like languages.)

Full closures are what LISP programmers call FUNARGs.

First, a simple example: 

   type Integer_Map_Type is access function (N: Integer) return Integer;

   function Add_M_To (M: Integer) return Integer_Map_Type is
      -- A function that returns M more than its formal parameter: 
      function Result_Function (N: Integer) return Integer is
      begin
         return N + M;
      end Result_Function;
   begin
      return Result_Function'Access;  -- illegal in Ada 95
   end Add_M_To;

   Add_1_To : Integer_Map_Type := Add_M_To(M => 1);
   Add_5_To : Integer_Map_Type := Add_M_To(M => 5);
   X        : Integer := Add_1_To(10); -- returns 11
   Y        : Integer := Add_5_To(10); -- returns 15

Add_M_To returns a pointer to a function more deeply nested than the
access type Integer_Map_Type, in violation of Ada-95 rules.  Note that
the function pointed to, Result_Function, refers to M, which is a formal
parameter of Add_M_To and thus, in Ada 95, goes out of existence when
Add_M_To returns.  In a language supporting full closures, the value of M
is not obliterated when Add_M_To returns.  What Add_M_To returns is a
value designating not only the function Result_Function, but also the
environment in which that function is to be executed, in this case an
environment in which M is bound to 1 or to 5.  The state of the
environment during the call on Add_M_To is retained as part of this
result value even after Add_M_To returns.

Now for a more intricate example.  Robert Dewar mentioned that
Ackermann's function can be programmed out of straightforward loops if
full closures are supported.  The classic definition of Ackermann's
function is: 

   A(0,n) = n+1
   A(m,0) = A(m-1,1)        for m>0
   A(m,n) = A(m-1,A(m,n-1)) for m>0, n>0

If we view A as an unbounded array and let R[m] be the function
corresponding to the m\th "row" of this array, so that A(m,n) = R[m](n),
these equations become: 

   R[0](n) = n+1
   R[m](0) = R[m-1](1)          for m>0
   R[m](n) = R[m-1] o R[m](n-1) for m>0, n>0
      (where o represents functional composition)

By repeatedly replacing R[m](...) in the third equation by the definition
for R[m] given in the third equation, we get, for m>0: 

   R[m](n) = R[m-1] o R[m](n-1)
           = R[m-1] o R[m-1] o R[m](n-2)
           = R[m-1] o R[m-1] o R[m-1] o R[m](n-3)
              ...
           = R[m-1] o ... o R[m-1] o R[m](0)
             \                   /
              \-----------------/
                    n times

Then, by replacing R[m](0) according to the second equation, we get

   R[m](n) = R[m-1] o ... o R[m-1] (1)
             \                   /
              \-----------------/
                   n+1 times

In other words,

   R[0] = the successor function (from the first equation)
   For m>0, the function R[m] is derived from the function R[m-1] as follows: 
      Given an argument n, R[m] returns the result of starting with 1 and
      applying R[m-1] repeatedly, n+1 times.

Here's a formulation using Ada plus full closures: 


package Unbounded_Naturals is
   type Unbounded_Natural is private;
      -- a type representing arbitrarily large nonnegative integers
   ...
   function "+"
      (Left: Unbounded_Natural; Right: Natural) return Unbounded_Natural;
   function "-"
      (Left: Unbounded_Natural; Right: Natural) return Unbounded_Natural;
   function "="
      (Left: Unbounded_Natural; Right: Natural) return Boolean;
   function To_Unbounded_Natural (N: Natural) return Unbounded_Natural;
   ...
private
   ...
end Unbounded_Naturals;


with Unbounded_Naturals; use Unbounded_Naturals;
package Ackermann_Computation is
   function Ackermann (M, N: Integer) return Unbounded_Natural;
end Ackermann_Computation;


package body Ackermann_Computation is

   type Ackermann_Row_Type is
      access function (N: Unbounded_Natural) return Unbounded_Natural;

   function Row_Zero (N: Unbounded_Natural) return Unbounded_Natural is
   begin
      return N + 1;
   end Row_Zero;

   function Successor_Row
      (F: Ackermann_Row_Type) return Ackermann_Row_Type is

      function Next_Row (N: Unbounded_Natural) return Unbounded_Natural is
         Counter : Unbounded_Natural := N + 1;
         Result  : Unbounded_Natural := 1;
      begin
         while Counter /= 0 loop
            Result := F(Result);
               -- F is the parameter of the surrounding function
            Counter := Counter - 1;
         end loop;
         return Result;
      end Result;

   begin

      return Next_Row'Access;  -- Illegal in Ada 95

   end Successor_Row;

   function Ackermann (M, N: Integer) return Unbounded_Natural is
      Row: Ackermann_Row_Type := Row_Zero'Access;  -- R[0]
   begin
      for I in 1 .. M loop
         Row := Successor_Row(Row);
            -- Compute R[1] from R[0], R[2] from R[1], ...
      end loop;
      return Row ( To_Unbounded_Natural(N) );  -- i.e., R[m](n)
   end Ackermann;

end Ackermann_Computation;


The magic is inside Successor_Row, which returns a pointer to a function
more deeply nested than the access type Ackermann_Row_Type, in violation
of Ada-95 rules.  The function pointed to, Next_Row, refers to F, which
is a formal parameter of Successor_Row.  Successor_Row returns a value
designating both the function Next_Row and the environment in which that
function is to be executed, in which F is bound to a particular
Ackermann_Row_Type value.  (After each iteration of the for-loop, Row
designates the function Next_Row and an environment in which F is bound
to whatever the value of Row was at the BEGINNING of that iteration.)

--
Norman H. Cohen    ncohen@watson.ibm.com




  reply	other threads:[~1996-07-08  0:00 UTC|newest]

Thread overview: 133+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-07-02  0:00 Q: access to subprogram tmoran
1996-07-02  0:00 ` Robert A Duff
1996-07-02  0:00   ` Robert Dewar
1996-07-03  0:00   ` Fergus Henderson
1996-07-03  0:00     ` Robert A Duff
1996-07-03  0:00       ` Adam Beneschan
1996-07-03  0:00         ` Robert Dewar
1996-07-03  0:00         ` Robert A Duff
1996-07-09  0:00         ` Thomas Wolff
1996-07-03  0:00       ` Robert Dewar
1996-07-03  0:00   ` Jon S Anthony
1996-07-03  0:00     ` Robert A Duff
1996-07-08  0:00       ` Norman H. Cohen
1996-07-09  0:00         ` Robert A Duff
1996-07-03  0:00     ` Mark A Biggar
1996-07-03  0:00       ` Robert A Duff
1996-07-03  0:00         ` Robert Dewar
1996-07-09  0:00         ` Thomas Wolff
1996-07-09  0:00           ` Robert Dewar
1996-07-10  0:00           ` Robert A Duff
1996-07-10  0:00             ` Richard A. O'Keefe
1996-07-10  0:00               ` Robert A Duff
1996-07-10  0:00                 ` Thomas Wolff
1996-07-10  0:00                   ` Robert Dewar
1996-07-10  0:00                   ` Robert A Duff
1996-07-10  0:00               ` Robert Dewar
1996-07-03  0:00       ` Robert Dewar
1996-07-06  0:00         ` Robert A Duff
1996-07-08  0:00           ` Norman H. Cohen [this message]
1996-07-08  0:00             ` Robert Dewar
1996-07-11  0:00             ` Robert A Duff
1996-07-12  0:00               ` Robert A Duff
1996-07-14  0:00               ` Norman H. Cohen
1996-07-03  0:00     ` Robert Dewar
1996-07-19  0:00     ` Brian Rogoff
1996-07-22  0:00       ` Richard A. O'Keefe
1996-07-23  0:00       ` Brian Rogoff
1996-07-23  0:00         ` Robert A Duff
1996-07-26  0:00         ` Brian Rogoff
1996-07-28  0:00           ` Robert A Duff
1996-07-22  0:00     ` Brian Rogoff
1996-07-23  0:00       ` Robert A Duff
1996-07-24  0:00       ` Richard A. O'Keefe
1996-07-26  0:00         ` Ken Garlington
1996-07-30  0:00           ` Richard A. O'Keefe
1996-07-24  0:00       ` Brian Rogoff
1996-07-26  0:00         ` Robert A Duff
1996-07-30  0:00         ` Brian Rogoff
1996-07-24  0:00     ` Brian Rogoff
1996-07-26  0:00     ` Richard A. O'Keefe
1996-07-28  0:00       ` Fergus Henderson
1996-07-28  0:00       ` Robert A Duff
1996-07-29  0:00         ` Richard A. O'Keefe
1996-07-29  0:00           ` Robert A Duff
1996-07-29  0:00     ` Richard A. O'Keefe
1996-07-30  0:00     ` Jon S Anthony
1996-07-05  0:00   ` Jon S Anthony
1996-07-06  0:00     ` Robert Dewar
1996-07-06  0:00     ` Robert A Duff
1996-07-06  0:00       ` Robert Dewar
1996-07-08  0:00         ` Robert A Duff
1996-07-08  0:00       ` Richard A. O'Keefe
1996-07-08  0:00         ` Robert A Duff
1996-07-08  0:00           ` Robert Dewar
1996-07-08  0:00         ` Robert Dewar
1996-07-10  0:00           ` Richard A. O'Keefe
1996-07-10  0:00             ` Robert Dewar
1996-07-19  0:00               ` Richard A. O'Keefe
1996-07-07  0:00   ` Ronald Cole
1996-07-07  0:00     ` Robert Dewar
1996-07-07  0:00       ` Richard Kenner
1996-07-07  0:00         ` Robert Dewar
1996-07-14  0:00       ` Ronald Cole
1996-07-14  0:00         ` Richard Kenner
1996-07-15  0:00           ` Fergus Henderson
1996-07-15  0:00             ` Robert Dewar
1996-07-17  0:00               ` Adam Beneschan
1996-07-17  0:00               ` Fergus Henderson
1996-07-17  0:00                 ` Richard Kenner
1996-07-20  0:00               ` Michael Feldman
1996-07-20  0:00                 ` Robert Dewar
1996-07-16  0:00             ` Richard Kenner
1996-07-07  0:00     ` Richard Kenner
1996-07-07  0:00   ` Mark Eichin
1996-07-08  0:00     ` Richard Kenner
1996-07-08  0:00   ` Brian Rogoff
1996-07-11  0:00     ` Norman H. Cohen
1996-07-11  0:00       ` Magnus Kempe
1996-07-11  0:00         ` Robert Dewar
1996-07-09  0:00   ` Jon S Anthony
1996-07-09  0:00     ` Robert Dewar
1996-07-09  0:00     ` Robert Dewar
1996-07-09  0:00   ` Jon S Anthony
1996-07-09  0:00     ` Robert Dewar
1996-07-10  0:00   ` Ronald Cole
1996-07-11  0:00     ` Richard Kenner
1996-07-11  0:00     ` Robert Dewar
1996-07-11  0:00   ` Jon S Anthony
1996-07-11  0:00   ` Jon S Anthony
1996-07-11  0:00     ` Robert Dewar
1996-07-11  0:00   ` Jon S Anthony
1996-07-11  0:00     ` Robert Dewar
1996-07-15  0:00       ` Mark A Biggar
1996-07-15  0:00         ` Robert Dewar
1996-07-11  0:00     ` Tucker Taft
1996-07-17  0:00       ` Brian Rogoff
1996-07-12  0:00     ` Jon S Anthony
1996-07-12  0:00       ` Robert Dewar
1996-07-15  0:00     ` Jon S Anthony
1996-07-15  0:00       ` Robert Dewar
1996-07-12  0:00   ` Brian Rogoff
1996-07-16  0:00     ` Magnus Kempe
1996-07-14  0:00   ` Ronald Cole
1996-07-14  0:00     ` Robert Dewar
1996-07-15  0:00   ` Jon S Anthony
1996-07-15  0:00     ` Robert Dewar
1996-07-16  0:00   ` Brian Rogoff
1996-07-24  0:00 ` Jon S Anthony
1996-07-25  0:00 ` Fergus Henderson
1996-07-25  0:00   ` David Kristola
1996-07-26  0:00     ` Robert A Duff
1996-07-30  0:00       ` Thomas Wolff
1996-07-30  0:00         ` Robert A Duff
1996-07-30  0:00       ` David Kristola
1996-07-26  0:00   ` Robert A Duff
1996-07-26  0:00     ` Fergus Henderson
1996-07-28  0:00       ` Robert A Duff
1996-07-28  0:00         ` Fergus Henderson
1996-07-25  0:00 ` Jon S Anthony
  -- strict thread matches above, loose matches on Subject: below --
1996-07-05  0:00 tmoran
1996-07-06  0:00 ` Robert A Duff
1996-07-15  0:00 tmoran
1996-07-15  0:00 ` Robert Dewar
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox