comp.lang.ada
 help / color / mirror / Atom feed
* Limited_Controlled and constructor functions
@ 2007-01-18  9:51 Maciej Sobczak
  2007-01-18 12:13 ` AW: " Grein, Christoph (Fa. ESG)
  2007-01-18 16:41 ` Robert A Duff
  0 siblings, 2 replies; 10+ messages in thread
From: Maciej Sobczak @ 2007-01-18  9:51 UTC (permalink / raw)


Hi,

Consider another Limited_Controlled problem:

-- p.ads:
with Ada.Finalization;
package P is
    type T (<>) is private;
    function Constructor(I : Integer) return T;
private
    type Array_Of_Ints is array (Positive range <>) of Integer;
    type T (Size : Positive) is new Ada.Finalization.Controlled with
       record
          A : Array_Of_Ints(1..Size);
       end record;
end P;

-- p.adb:
package body P is
    function Constructor(I : Integer) return T is
    begin
       return T'(Ada.Finalization.Controlled with
                 Size => 1, A => (1 => I));
    end Constructor;
end P;

It looks a bit convoluted. :-)
The idea is to have a T type that contains the array of integers and a 
constructor function that creates T with single element in the contained 
array. T is private, controlled and indefinite, to force the use of 
constructor function whenever T is declared.

Now, I want to make it limited as well by adding limited before private 
and changing Controlled to Limited_Controlled in two places.
I get this when compiling the package:

cannot return a local value by reference
"Program_Error" will be raised at run time

What's going on?

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* AW: Limited_Controlled and constructor functions
  2007-01-18  9:51 Limited_Controlled and constructor functions Maciej Sobczak
@ 2007-01-18 12:13 ` Grein, Christoph (Fa. ESG)
  2007-01-18 16:41 ` Robert A Duff
  1 sibling, 0 replies; 10+ messages in thread
From: Grein, Christoph (Fa. ESG) @ 2007-01-18 12:13 UTC (permalink / raw)
  To: comp.lang.ada

> Now, I want to make it limited as well by adding limited before
private 
> and changing Controlled to Limited_Controlled in two places.
> I get this when compiling the package:

> cannot return a local value by reference
> "Program_Error" will be raised at run time

I think the compiler is not yet full Ada 2005; this should work if I
have understood the RM correctly.




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

* Re: Limited_Controlled and constructor functions
  2007-01-18  9:51 Limited_Controlled and constructor functions Maciej Sobczak
  2007-01-18 12:13 ` AW: " Grein, Christoph (Fa. ESG)
@ 2007-01-18 16:41 ` Robert A Duff
  2007-01-19  7:58   ` Maciej Sobczak
  1 sibling, 1 reply; 10+ messages in thread
From: Robert A Duff @ 2007-01-18 16:41 UTC (permalink / raw)


Maciej Sobczak <no.spam@no.spam.com> writes:

> Hi,
>
> Consider another Limited_Controlled problem:
>
> -- p.ads:
> with Ada.Finalization;
> package P is
>    type T (<>) is private;
>    function Constructor(I : Integer) return T;
> private
>    type Array_Of_Ints is array (Positive range <>) of Integer;
>    type T (Size : Positive) is new Ada.Finalization.Controlled with
>       record
>          A : Array_Of_Ints(1..Size);
>       end record;
> end P;
>
> -- p.adb:
> package body P is
>    function Constructor(I : Integer) return T is
>    begin
>       return T'(Ada.Finalization.Controlled with
>                 Size => 1, A => (1 => I));
>    end Constructor;
> end P;
>
> It looks a bit convoluted. :-)
> The idea is to have a T type that contains the array of integers and a
> constructor function that creates T with single element in the contained
> array. T is private, controlled and indefinite, to force the use of
> constructor function whenever T is declared.
>
> Now, I want to make it limited as well by adding limited before private
> and changing Controlled to Limited_Controlled in two places.
> I get this when compiling the package:
>
> cannot return a local value by reference
> "Program_Error" will be raised at run time
>
> What's going on?

It works in Ada 2005.  It's one of my favorite features of Ada 2005.
(By the way, I did part of the work of implementing this in GNAT.  The
way it works internally is "interesting", because it is important that
the above "return" not make a copy; it must build the new object in its
final resting place.)

Limited types were somewhat broken in Ada 83.  We tried to fix them in
Ada 95, but the "return by reference" idea was another mistake.
That's fixed in Ada 2005.

I'm not entirely sure what you're trying to accomplish, since the length
of that array can't change, and there's nothing interesting for Finalize
to do in this example.  Maybe you have other constructors?

Anyway, you can do things like this:

with Ada.Finalization;
package P is
   type T (Length : Natural; Initial : Integer) is private;
   function Constructor(I : Integer) return T;
private
   type Array_Of_Ints is array (Positive range <>) of Integer;
   type T (Length : Natural; Initial : Integer) is new Ada.Finalization.Limited_Controlled with
      record
         A : Array_Of_Ints(1..Length) := (others => Initial);
      end record;
end P;

My_Object : P.T (Length => 1, Initial => 123);

but I'm not sure if that's what you want.  The point is, in Ada 95,
limited types cannot have constructor functions, which is annoying,
but you can often work around the problem by passing information in
as discriminants.

- Bob



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

* Re: Limited_Controlled and constructor functions
  2007-01-18 16:41 ` Robert A Duff
@ 2007-01-19  7:58   ` Maciej Sobczak
  2007-01-19  9:41     ` Dmitry A. Kazakov
  2007-01-20 17:09     ` Gautier
  0 siblings, 2 replies; 10+ messages in thread
From: Maciej Sobczak @ 2007-01-19  7:58 UTC (permalink / raw)


Robert A Duff wrote:

> It works in Ada 2005.

That's good news. :-)

> It's one of my favorite features of Ada 2005.

It's one of the many features that are essential for writing robust 
code, IMHO (from the C++ perspective).

> I'm not entirely sure what you're trying to accomplish, since the length
> of that array can't change, and there's nothing interesting for Finalize
> to do in this example.  Maybe you have other constructors?

Yes, there are other constructors that accept more parameters and that 
create longer arrays.

What I want to accomplish is the functional way of building lists of 
values of variant types:

P : constant Params := Make_Params(Param("Hello"),
                                    Param("Ada"),
                                    Param(12),
                                    Param(3.14)));

Make_Params is a constructor function that creates a list of 4 
parameters, each of them being a variant. I wanted to be able to store 
Strings in the variant without constraining their lengths (which is 
impossible), so I decided to use access variable that points to 
unconstrained String. I migh use Unbounded_String as well, but I don't 
yet see what would be the difference.
Everything should be nicely cleaned up after that - that's why Params is 
controlled, and since I don't want to bother with copy semantics, it is 
also limited.

It is part of the simple database binding that I wanted to write for the 
sake of exercise.
I will make the whole public once it's finished (but I need Ada2005 
compiler for that! :-) ).

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Limited_Controlled and constructor functions
  2007-01-19  7:58   ` Maciej Sobczak
@ 2007-01-19  9:41     ` Dmitry A. Kazakov
  2007-01-19 13:45       ` Maciej Sobczak
  2007-01-20 17:09     ` Gautier
  1 sibling, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2007-01-19  9:41 UTC (permalink / raw)


On Fri, 19 Jan 2007 08:58:54 +0100, Maciej Sobczak wrote:

> What I want to accomplish is the functional way of building lists of 
> values of variant types:
> 
> P : constant Params := Make_Params(Param("Hello"),
>                                     Param("Ada"),
>                                     Param(12),
>                                     Param(3.14)));

Hmm, but should the parameters and containers of be limited types? I find
it rather natural to be able to copy parameter(s), send them over IP...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Limited_Controlled and constructor functions
  2007-01-19  9:41     ` Dmitry A. Kazakov
@ 2007-01-19 13:45       ` Maciej Sobczak
  2007-01-19 14:33         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: Maciej Sobczak @ 2007-01-19 13:45 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Fri, 19 Jan 2007 08:58:54 +0100, Maciej Sobczak wrote:
> 
>> What I want to accomplish is the functional way of building lists of 
>> values of variant types:
>>
>> P : constant Params := Make_Params(Param("Hello"),
>>                                     Param("Ada"),
>>                                     Param(12),
>>                                     Param(3.14)));
> 
> Hmm, but should the parameters and containers of be limited types?

Probably not, but...

> I find
> it rather natural to be able to copy parameter(s)

... I don't like to overengineer things in anticipation of usage 
patterns that actually might never happen. I prefer to forbid it and 
wait until it's asked for. I find it easier (well, I at least expected) 
to forbid copy semantics than to implement it.

In C++ it's two lines of code or even half:

class MyClass : boost::noncopyable
...

;-)

 > send them over IP...

Then we're talking about serialization. Limited types don't forbid it.

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Limited_Controlled and constructor functions
  2007-01-19 13:45       ` Maciej Sobczak
@ 2007-01-19 14:33         ` Dmitry A. Kazakov
  2007-01-22  8:59           ` Maciej Sobczak
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2007-01-19 14:33 UTC (permalink / raw)


On Fri, 19 Jan 2007 14:45:59 +0100, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
>> On Fri, 19 Jan 2007 08:58:54 +0100, Maciej Sobczak wrote:
>> 
>>> What I want to accomplish is the functional way of building lists of 
>>> values of variant types:
>>>
>>> P : constant Params := Make_Params(Param("Hello"),
>>>                                     Param("Ada"),
>>>                                     Param(12),
>>>                                     Param(3.14)));
>> 
>> Hmm, but should the parameters and containers of be limited types?
> 
> Probably not, but...
> 
>> I find it rather natural to be able to copy parameter(s)
> 
> ... I don't like to overengineer things in anticipation of usage 
> patterns that actually might never happen. I prefer to forbid it and 
> wait until it's asked for.

But you used ":=", which was (no matter what RM says (:-)) a primitive
operation undefined for limited types. Prior Ada 2005 it was, now, ":=" in
declarations has a different meaning than in statements...

> In C++ it's two lines of code or even half:
> 
> class MyClass : boost::noncopyable
> ...

Huh, C++ has even weaker means to describe formal types contracts. It has
dire <class T>. In Ada there is limited, tagged, range <> etc. Far too
weak, IMO, but still better than C++.

Anyway, there must be a reason why you wanted to have a compound parameters
object rather than to specify them directly in the factory function. You
didn't say what was the goal. To have an abstract factory? I have a
suspicion that it wouldn't work anyway. BTW, you could try streams and
getting the object directly from the stream instead.

>  > send them over IP...
> 
> Then we're talking about serialization.

Egh, no, serialization is ordering in time. To be able to copy is about
lack of identity and memory-isotropy.

> Limited types don't forbid it.

Limited types is a kludge. There should be a simpler and clearer way to say
that the thingy has no visible compiler-generated copy constructor, no
equality, no aggregates, no assignment (in Ada 95). All these are just
primitive operations or parts of.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Limited_Controlled and constructor functions
  2007-01-19  7:58   ` Maciej Sobczak
  2007-01-19  9:41     ` Dmitry A. Kazakov
@ 2007-01-20 17:09     ` Gautier
  2007-01-20 19:39       ` Gautier
  1 sibling, 1 reply; 10+ messages in thread
From: Gautier @ 2007-01-20 17:09 UTC (permalink / raw)


Maciej Sobczak:

> What I want to accomplish is the functional way of building lists of 
> values of variant types:
> 
> P : constant Params := Make_Params(Param("Hello"),
>                                    Param("Ada"),
>                                    Param(12),
>                                    Param(3.14)));

Would you be happy with the following ? For the fun, I did it in Ada 83 :-).
You can change that with Unbounded_String's and make things nicely, hidden, 
private, tagged and so on as you like... Note that the function Make_Params 
was superfluous in that implementation.

Output:
Parameter # 1: [Hello]
Parameter # 2: [Ada]
Parameter # 3: [ 12]
Parameter # 4: [ 3.14000E+00]

--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
-- start 17:35
-- stop  17:59

pragma Ada_83;

with Text_IO, Variant_pkg;

procedure Variants is
   use Variant_pkg;

   P : constant Params := (Param("Hello"),
                           Param("Ada"),
                           Param(12),
                           Param(3.14));
begin
   for i in P'Range loop
     Text_IO.Put_Line(
       "Parameter #" & Integer'Image(i) & ": [" & Image(P(i).all) & ']'
     );
   end loop;
end Variants;
--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
package Variant_pkg is

   type BorString( maxlength: Positive ) is record
     length: Natural:= 0;
     s: String( 1..maxlength );
   end record;

   type Kind is (A_String, An_Integer, A_Float);

   xamax: constant:= 1024;

   type Atom(k: Kind) is record
     case k is
       when A_String   => s: BorString(xamax);
       when An_Integer => i: Integer;
       when A_Float    => f: Float;
     end case;
   end record;

   type p_Atom is access Atom;

   type Params is array(Positive range <>) of p_Atom;

   function Param(s: String) return p_Atom;
   function Param(i: Integer) return p_Atom;
   function Param(f: Float) return p_Atom;

   function Image(a: Atom) return String;

end Variant_pkg;
--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
package body Variant_pkg is
   function Param(s: String) return p_Atom is
     a: p_Atom:= new Atom(A_String);
   begin
     a.s.s(1..s'Length):= s;
     a.s.length:= s'Length;
     return a;
   end Param;

   function Param(i: Integer) return p_Atom is
     a: p_Atom:= new Atom(An_Integer);
   begin
     a.i:= i;
     return a;
   end Param;

   function Param(f: Float) return p_Atom is
     a: p_Atom:= new Atom(A_Float);
   begin
     a.f:= f;
     return a;
   end Param;

   function Image(a: Atom) return String is
   begin
     case a.k is
       when A_String   => return a.s.s(1..a.s.length);
       when An_Integer => return Integer'Image(a.i);
       when A_Float    => return Float'Image(a.f);
     end case;
   end Image;

end Variant_pkg;
______________________________________________________________
Gautier         -- http://www.mysunrise.ch/users/gdm/index.htm
Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



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

* Re: Limited_Controlled and constructor functions
  2007-01-20 17:09     ` Gautier
@ 2007-01-20 19:39       ` Gautier
  0 siblings, 0 replies; 10+ messages in thread
From: Gautier @ 2007-01-20 19:39 UTC (permalink / raw)


Oh, and a version without implicit dynamic allocation at all:

--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
pragma Ada_83;

with Text_IO, Variant_pkg;

procedure Variants is
   use Variant_pkg;

   P : constant Params := (Param("Hello"),
                           Param("Ada"),
                           Param(12),
                           Param(3.14));
begin
   for i in P'Range loop
     Text_IO.Put_Line(
       "Parameter #" & Integer'Image(i) & ": [" & Image(P(i)) & ']'
     );
   end loop;
end Variants;
--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
package Variant_pkg is

   type BorString( maxlength: Positive ) is record
     length: Natural:= 0;
     s: String( 1..maxlength );
   end record;

   type Kind is (A_String, An_Integer, A_Float);

   xamax: constant:= 1024;

   type Atom(k: Kind:= An_Integer) is record
     case k is
       when A_String   => s: BorString(xamax);
       when An_Integer => i: Integer;
       when A_Float    => f: Float;
     end case;
   end record;

   type Params is array(Positive range <>) of Atom;

   function Param(s: String) return Atom;
   function Param(i: Integer) return Atom;
   function Param(f: Float) return Atom;

   function Image(a: Atom) return String;

end Variant_pkg;
--8<-----------8<-----------8<-----------8<-----------8<-----------8<---------
package body Variant_pkg is

   function Param(s: String) return Atom is
     a: Atom(A_String);
   begin
     a.s.s(1..s'Length):= s;
     a.s.length:= s'Length;
     return a;
   end Param;

   function Param(i: Integer) return Atom is
   begin
     return Atom'(k => An_Integer, i => i);
   end Param;

   function Param(f: Float) return Atom is
   begin
     return Atom'(k => A_Float, f => f);
   end Param;

   function Image(a: Atom) return String is
   begin
     case a.k is
       when A_String   => return a.s.s(1..a.s.length);
       when An_Integer => return Integer'Image(a.i);
       when A_Float    => return Float'Image(a.f);
     end case;
   end Image;

end Variant_pkg;



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

* Re: Limited_Controlled and constructor functions
  2007-01-19 14:33         ` Dmitry A. Kazakov
@ 2007-01-22  8:59           ` Maciej Sobczak
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej Sobczak @ 2007-01-22  8:59 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>> In C++ it's two lines of code or even half:
>>
>> class MyClass : boost::noncopyable
>> ...
> 
> Huh, C++ has even weaker means to describe formal types contracts. It has
> dire <class T>. In Ada there is limited, tagged, range <> etc. Far too
> weak, IMO, but still better than C++.

Yes, except that I'm not suprised by what C++ offers with regard to 
class definitions. I was very surprised by the semantics of Controlled 
and Limited_Controlled and their funny effects on other parts of my program.

>>  > send them over IP...
>>
>> Then we're talking about serialization.
> 
> Egh, no, serialization is ordering in time.

You are right. Me too:

http://en.wikipedia.org/wiki/Serialization

> To be able to copy is about
> lack of identity and memory-isotropy.

Not really. Memory isotropy (cool technical buzz, btw ;-) ) is about 
memcpy and memmove. Copy semantics is about what happens when you use 
relevant language constructs. If memory isotropy is a property of any 
given type, then copy semantics can be automatically derived. Otherwise 
it has to be explicitly defined.

>> Limited types don't forbid it.
> 
> Limited types is a kludge.

A particularly nasty one.

> There should be a simpler and clearer way to say
> that the thingy has no visible compiler-generated copy constructor, no
> equality, no aggregates, no assignment

Amen.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

end of thread, other threads:[~2007-01-22  8:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-18  9:51 Limited_Controlled and constructor functions Maciej Sobczak
2007-01-18 12:13 ` AW: " Grein, Christoph (Fa. ESG)
2007-01-18 16:41 ` Robert A Duff
2007-01-19  7:58   ` Maciej Sobczak
2007-01-19  9:41     ` Dmitry A. Kazakov
2007-01-19 13:45       ` Maciej Sobczak
2007-01-19 14:33         ` Dmitry A. Kazakov
2007-01-22  8:59           ` Maciej Sobczak
2007-01-20 17:09     ` Gautier
2007-01-20 19:39       ` Gautier

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