comp.lang.ada
 help / color / mirror / Atom feed
* Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
  1999-04-07  0:00 Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Daniel Wengelin
  1999-04-07  0:00 ` David C. Hoos, Sr.
  1999-04-07  0:00 ` Robert Dewar
@ 1999-04-07  0:00 ` Tucker Taft
  2 siblings, 0 replies; 5+ messages in thread
From: Tucker Taft @ 1999-04-07  0:00 UTC (permalink / raw)


Daniel Wengelin (dawe@celsiustech.se) wrote:


: When looking around for some infomration about OOP I came across the
: article http://www.adahome.com/articles/1998-02/ar_lessons95.html.

: When skimming through, I noted the following section
: ----------------------------------------- COPY FROM ADAHOME
: ---------------------------------
: The ability to pass subprograms as parameters is one of the nicest features
: of Ada 95 (it didn't exist in Ada 83). But accessibility rules make it
: useless within a multi-tasking program. Indeed, access to a local procedure
: cannot be used as a parameter of a more globally declared procedure (e.g. a
: class method). ...
: ...
: I gave the code a try with Gnat 3.11 as follows.

: generic
:    type Item_T is private;
: package List is
:    type Node;
:    type Object is access Node;
:    type Node is record
:       I : Item_T;
:       Next:Object;
:    end record;

:    type Action_Proc is access procedure
:      (I : in out Item_T);
:    procedure Iterate
:      (The_Action : Action_Proc;
:       Through_List : Object);
: end List;

: ---------------------------
: package body List is
:    procedure Iterate
:      (The_Action : Action_Proc;
:       Through_List : Object)
:    is
:       Current : Object := Through_List;
:    begin
:       while Current /= null loop
:          The_Action(Current.I);
:          Current := Current.Next;
:       end loop;
:    end Iterate;
: end List;

: ------------------------

: procedure List_Test is

:    procedure Print (C: in out Character) is
:    begin
:       Ada.Text_Io.Put(C);
:       Ada.Text_Io.New_Line;
:    end Print;
:    package C_List is new List(Character);

:    The_List : C_List.Object := null;
: begin
:    for I in Character range 'a' .. 'e' loop
:       The_List := new C_List.Node'(I, The_List);
:    end loop;

:    C_List.Iterate (Print'Access, The_List);
: end List_Test;

: The above source compiled and ran without any problems. So, did I
: misunderstand or is Gnat wrong or is the article in AdaHome wrong?

The critical difference between your code and the code on AdaHome
is that your instantiation of the generic is at the same accessibility
level as the function named in the prefix to 'Access.  The code
in AdaHome might be able to work the same way, by moving their instantiation
so that it is inside the outer subprogram.  But there also may be reasons
why they didn't want the instantiation itself nested.

In any case, one way to address these "multitasking" problems is
to add an additional class-wide parameter through which additional
data can be passed through to a global function.

: thanks.

:   Daniel

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
  1999-04-07  0:00 Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Daniel Wengelin
@ 1999-04-07  0:00 ` David C. Hoos, Sr.
  1999-04-07  0:00   ` Daniel Wengelin
  1999-04-07  0:00 ` Robert Dewar
  1999-04-07  0:00 ` Tucker Taft
  2 siblings, 1 reply; 5+ messages in thread
From: David C. Hoos, Sr. @ 1999-04-07  0:00 UTC (permalink / raw)



Daniel Wengelin wrote in message <01be80c2$114e0890$c24d3a8b@m04w0588>...
>
>
>When looking around for some infomration about OOP I came across the
>article http://www.adahome.com/articles/1998-02/ar_lessons95.html.
>
<large snip>

>I gave the code a try with Gnat 3.11 as follows.
>
>generic
>   type Item_T is private;
>package List is
>   type Node;
>   type Object is access Node;
>   type Node is record
>      I : Item_T;
>      Next:Object;
>   end record;
>
>   type Action_Proc is access procedure
>     (I : in out Item_T);
>   procedure Iterate
>     (The_Action : Action_Proc;
>      Through_List : Object);
>end List;
>
>---------------------------
>package body List is
>   procedure Iterate
>     (The_Action : Action_Proc;
>      Through_List : Object)
>   is
>      Current : Object := Through_List;
>   begin
>      while Current /= null loop
>         The_Action(Current.I);
>         Current := Current.Next;
>      end loop;
>   end Iterate;
>end List;
>
>------------------------
>
>procedure List_Test is
>
>   procedure Print (C: in out Character) is
>   begin
>      Ada.Text_Io.Put(C);
>      Ada.Text_Io.New_Line;
>   end Print;
>   package C_List is new List(Character);
>
>   The_List : C_List.Object := null;
>begin
>   for I in Character range 'a' .. 'e' loop
>      The_List := new C_List.Node'(I, The_List);
>   end loop;
>
>   C_List.Iterate (Print'Access, The_List);
>end List_Test;
>
>The above source compiled and ran without any problems. So, did I
>misunderstand or is Gnat wrong or is the article in AdaHome wrong?
>

Well, you must have an amazing version of gnat-3.11, for your code
won't compile either without the required context clauses for
Ada.Text_IO, and List in the List_Test source file ;).

But, seriously, I am glad to say Jean-Marie Dautelle is incorrect
in the article you cited.

Indeed I have used access to subprograms many times in multi-tasking
programs.  The basic rule is that accesses to subprograms must
not have a lifetime greater than that of the subprogram.

So, in your example, even though the procedure Print only exists
during the execution of procedure List_Test, there is no problem
because the lifetime of Print cannot be less than that of the
access type C_List.Action_Proc;

Frequently, all this limitation means is that the subprogram must
be declared at library level -- i.e. such that the lifetime of
the subprogram is the same as that of the main program.

For example, if you make this small change to your code (leaving
the generic List package unchanged, the program will not compile:

----
with List;
package C_List is new List(Character);
----
with Ada.Text_IO;
with C_List;
procedure List_Test is
   procedure Print (C: in out Character) is
   begin
      Ada.Text_IO.Put(C);
      Ada.Text_IO.New_Line;
   end Print;
   The_List : C_List.Object := null;
begin
   for I in Character range 'a' .. 'e' loop
      The_List := new C_List.Node'(I, The_List);
   end loop;

   C_List.Iterate (Print'Access, The_List);
end List_Test;
----

In this case, the access type C_List.Action_Proc could have a
lifetime greater than that of the subprogram Print.  When gcc
compiles List_Test, it has no way of knowing that List_Test
is the main program, so the compilation fails.  As the RM
puts it, the subprogram access level is deeper than that of
the access type, which is not allowed.

But what if the generic instantiation C_List is to be used
by more than one compilation unit, and therefore must be
declared at library level? Again, another small change makes
things well again.

with List;
package C_List is new List(Character);
----
with Ada.Text_IO;
procedure Print (C: in out Character) is
begin
   Ada.Text_IO.Put(C);
   Ada.Text_IO.New_Line;
end Print;
----
with C_List;
with Print;
procedure List_Test is
   The_List : C_List.Object := null;
begin
   for I in Character range 'a' .. 'e' loop
      The_List := new C_List.Node'(I, The_List);
   end loop;

   C_List.Iterate (Print'Access, The_List);
end List_Test;
----

Now, once again, the lifetime of Print is at least as long
as that of the access type C_List.Action_Proc.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
  1999-04-07  0:00 Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Daniel Wengelin
  1999-04-07  0:00 ` David C. Hoos, Sr.
@ 1999-04-07  0:00 ` Robert Dewar
  1999-04-07  0:00 ` Tucker Taft
  2 siblings, 0 replies; 5+ messages in thread
From: Robert Dewar @ 1999-04-07  0:00 UTC (permalink / raw)


In article <01be80c2$114e0890$c24d3a8b@m04w0588>,
  "Daniel Wengelin" <dawe@celsiustech.se> wrote:
> The ability to pass subprograms as parameters is one of
> the nicest features of Ada 95 (it didn't exist in Ada
> 83). But accessibility rules make it useless within a
> multi-tasking program.

Hmmm! I guess that means that Daniel thinks that procedure
pointers in C are also useless in multi-tasking programs!

The claim is very misleading. Remember this: the only time
that accessibility rules are an issue for procedure
parameters is for the case of nested procedures. To
eliminate the problem, make the procedures in question
global. Global procedures, as opposed to global variables,
are never a problem for tasking.

Now you can react and say, gosh, that's terrible not being
able to use pointers to local procedures in a completely
general manner, I can't live with that, the language is
useless. But then you are also saying that C, C++ and Java
are useless -- yes, I know some of the excessive rhetoric
from Ada fans seems to say that at times :-) But seriously,
we know that this is not the case!

P.S. GNAT contains a significant extension, namely the
Unrestricted_Access attribute for procedures, which
completely eliminates these accesibility checks for
procedures, and gives you the same functionality as
GNU C's nested procedures and procedure pointers. This
comes at a price:

(a) it is significantly non-portable. Some implementors
claimed it was impossible to provide this kind of
capability with displays, and this is one of the times
that the language design bent to the will of implementors.
Since some implementations (e.g. Aonix) still use displays
you cannot expect all Ada implementations to copy this
GNAT attribute.

(b) it is unsafe, since you can create dangling pointers,
and dangling procedure pointers are a particularly
unpleasant beast to have around!

Nevertheless it is a powerful facility. For a fairly
fundamental use of this facility in practice, see the
SPITBOL packages provided by GNAT.

Robert Dewar
Ada Core Technologies

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
@ 1999-04-07  0:00 Daniel Wengelin
  1999-04-07  0:00 ` David C. Hoos, Sr.
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Daniel Wengelin @ 1999-04-07  0:00 UTC (permalink / raw)




When looking around for some infomration about OOP I came across the
article http://www.adahome.com/articles/1998-02/ar_lessons95.html.

When skimming through, I noted the following section
----------------------------------------- COPY FROM ADAHOME
---------------------------------
The ability to pass subprograms as parameters is one of the nicest features
of Ada 95 (it didn't exist in Ada 83). But accessibility rules make it
useless within a multi-tasking program. Indeed, access to a local procedure
cannot be used as a parameter of a more globally declared procedure (e.g. a
class method). In practice, accessibility rules force the use of global
variable which makes multi-tasking very delicate. The only alternative is
to use generic parameters (parameterized methods), with the inconvenience
that parameterized methods are not inheritable. 

Example:

The following looks nice, but it will not compile! 

     generic
       type Item is private;
     package List is
        type Object is ...
        ...
        type Action is access procedure Action(
           The_Item : in out Item;
           Stop_Iterating : out Boolean);
        procedure Iterate (
           The_Action : Action
           Through : in List.Object);
        ...
     end List;
     
     with List, Student;
     package Student_List is
       new List (Item => Student.Object);
     
     with Student_List;
     function Retrieve_Student (With_Name : Student.Name;
                                From : Student_List.Object) return
Student.Object is

        The_Student_Found : Student.Object;

        procedure Find (The_Student : in out Student.Object;
                        Stop_Iterating : out Boolean) is
        begin
           if Student.Name_Of (The_Student) = With_Name then
              The_Student_Found := The_Student;
              Stop_Iterating := True;
           else
              Stop_Iterating := False;
           end if;
        end Find;

     begin
        Student_List.Iterate (The_Action => Find'Access,   -- Compilation
Error
                              Through => From);            
        return The_Student_Found;
     end Retrieve_Student;
------------------------------------- END COPY FROM ADAHOME
---------------------------------


I gave the code a try with Gnat 3.11 as follows.

generic
   type Item_T is private;
package List is
   type Node;
   type Object is access Node;
   type Node is record
      I : Item_T;
      Next:Object;
   end record;

   type Action_Proc is access procedure
     (I : in out Item_T);
   procedure Iterate
     (The_Action : Action_Proc;
      Through_List : Object);
end List;

---------------------------
package body List is
   procedure Iterate
     (The_Action : Action_Proc;
      Through_List : Object)
   is
      Current : Object := Through_List;
   begin
      while Current /= null loop
         The_Action(Current.I);
         Current := Current.Next;
      end loop;
   end Iterate;
end List;

------------------------

procedure List_Test is

   procedure Print (C: in out Character) is
   begin
      Ada.Text_Io.Put(C);
      Ada.Text_Io.New_Line;
   end Print;
   package C_List is new List(Character);

   The_List : C_List.Object := null;
begin
   for I in Character range 'a' .. 'e' loop
      The_List := new C_List.Node'(I, The_List);
   end loop;

   C_List.Iterate (Print'Access, The_List);
end List_Test;

The above source compiled and ran without any problems. So, did I
misunderstand or is Gnat wrong or is the article in AdaHome wrong?

thanks.

  Daniel






^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
  1999-04-07  0:00 ` David C. Hoos, Sr.
@ 1999-04-07  0:00   ` Daniel Wengelin
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Wengelin @ 1999-04-07  0:00 UTC (permalink / raw)




David C. Hoos, Sr. <david.c.hoos.sr@ada95.com> wrote in article 
> 
> Well, you must have an amazing version of gnat-3.11, for your code
> won't compile either without the required context clauses for
> Ada.Text_IO, and List in the List_Test source file ;).
> 


Ooops, the famous copy-paste bug. Sorry.

dan




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1999-04-07  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-04-07  0:00 Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Daniel Wengelin
1999-04-07  0:00 ` David C. Hoos, Sr.
1999-04-07  0:00   ` Daniel Wengelin
1999-04-07  0:00 ` Robert Dewar
1999-04-07  0:00 ` Tucker Taft

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