comp.lang.ada
 help / color / mirror / Atom feed
* Default value for a record component
@ 2007-07-21 21:19 Maciej Sobczak
  2007-07-22  8:08 ` Dmitry A. Kazakov
  2007-07-24  1:27 ` Randy Brukardt
  0 siblings, 2 replies; 10+ messages in thread
From: Maciej Sobczak @ 2007-07-21 21:19 UTC (permalink / raw)


Consider:

package P is
   type T is record
      V : Integer := 5;
   end record;
end P;

Above, T.V will have 5 as a default value whenever the instance of T
is created without any explicit initialization.

I would like extend it and do this:

package P is
   type T is record
      V : Integer := Get_Default_Value;
   end record;
private
   function Get_Default_Value return Integer;
end P;

without losing any of the properties of the original solution and
without "leaking" any implementation detail to the public view. The
idea is, of course, to compute the default value at run-time, each
time the new object is created - but without touching the general
"look&feel" of the original code (so that for example Controlled is
excluded).
Is it possible?

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




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

* Re: Default value for a record component
  2007-07-21 21:19 Default value for a record component Maciej Sobczak
@ 2007-07-22  8:08 ` Dmitry A. Kazakov
  2007-07-22 19:44   ` Maciej Sobczak
  2007-07-22 20:01   ` Jeffrey R. Carter
  2007-07-24  1:27 ` Randy Brukardt
  1 sibling, 2 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2007-07-22  8:08 UTC (permalink / raw)


On Sat, 21 Jul 2007 14:19:17 -0700, Maciej Sobczak wrote:

> Consider:
> 
> package P is
>    type T is record
>       V : Integer := 5;
>    end record;
> end P;
> 
> Above, T.V will have 5 as a default value whenever the instance of T
> is created without any explicit initialization.
> 
> I would like extend it and do this:
> 
> package P is
>    type T is record
>       V : Integer := Get_Default_Value;
>    end record;
> private
>    function Get_Default_Value return Integer;
> end P;
> 
> without losing any of the properties of the original solution and
> without "leaking" any implementation detail to the public view. The
> idea is, of course, to compute the default value at run-time, each
> time the new object is created - but without touching the general
> "look&feel" of the original code (so that for example Controlled is
> excluded).
> Is it possible?

Yes:

package P is
   function Get_Default_Value return Integer;
   type T is record
      V : Integer := Get_Default_Value;
   end record;
end P;

or even like this:

package P is
   Default_Value : Integer;
   type T is record
      V : Integer := Default_Value;
   end record;
end P;

The only problem with this design is that whatever things you wished to
pass to an instance of T, they will be enclosed in P (or it parents). This
is not a "closure." You could achieve a sort of closure, if you made P
generic and passed Get_Default_Value as a formal parameter. But that would
require an instantiation of P each time you wanted to change the things.

In Ada 2005 you can come a bit closer to closures:

package P is
   type T (Default_Value : access function return Integer) is limited
   record
      V : Integer := Default_Value.all;
   end record;
end P;

This looks awful because of pointers. There is still no true procedural
types in Ada, alas. Because of pointers, T has to be limited. Yet it is
almost closure and P can be pure:

   function Get_Default_Value return Integer;
   ...
   X : T (Get_Default_Value'Access);

Feels much better than:

   X : T := (V => Get_Default_Value);

!? (:-))

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



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

* Re: Default value for a record component
  2007-07-22  8:08 ` Dmitry A. Kazakov
@ 2007-07-22 19:44   ` Maciej Sobczak
  2007-07-22 21:44     ` Robert A Duff
  2007-07-22 20:01   ` Jeffrey R. Carter
  1 sibling, 1 reply; 10+ messages in thread
From: Maciej Sobczak @ 2007-07-22 19:44 UTC (permalink / raw)


On 22 Lip, 10:08, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>

> > I would like extend it and do this:
>
> > package P is
> >    type T is record
> >       V : Integer := Get_Default_Value;
> >    end record;
> > private
> >    function Get_Default_Value return Integer;
> > end P;
>
> > without losing any of the properties of the original solution and
> > without "leaking" any implementation detail to the public view.

> Yes:
>
> package P is
>    function Get_Default_Value return Integer;
>    type T is record
>       V : Integer := Get_Default_Value;
>    end record;
> end P;

No, this leaks the implementation detail (the Get_Default function) to
the public view and pollutes it. I don't want my users to even see it.

Ada needs real constructors, not just initial values.

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




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

* Re: Default value for a record component
  2007-07-22  8:08 ` Dmitry A. Kazakov
  2007-07-22 19:44   ` Maciej Sobczak
@ 2007-07-22 20:01   ` Jeffrey R. Carter
  1 sibling, 0 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2007-07-22 20:01 UTC (permalink / raw)


On Sat, 21 Jul 2007 14:19:17 -0700, Maciej Sobczak wrote:
>
> package P is
>    type T is record
>       V : Integer := Get_Default_Value;
>    end record;
> private
>    function Get_Default_Value return Integer;
> end P;

If your function is not very complicated, you can do something like

package P is
    Default_Value : constant Integer;

    type T is record
       V : Integer := Get_Default_Value;
    end record;
private
    Default_Value : constant Integer := 5;
end P;

If this won't work, and your intention is to keep P's clients from 
seeing the function, then you'll have to use a private type:

package P is
    type T is private;

    procedure Put (Into : out T; Value : in Integer);
    function Get (From : in T) return Integer;
private
    function Get return Integer;

    type T is record
       V : Integer := Get;
    end record;
end P;

-- 
Jeff Carter
"I'm a kike, a yid, a heebie, a hook nose! I'm Kosher,
Mum! I'm a Red Sea pedestrian, and proud of it!"
Monty Python's Life of Brian
77



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

* Re: Default value for a record component
  2007-07-22 19:44   ` Maciej Sobczak
@ 2007-07-22 21:44     ` Robert A Duff
  2007-07-23 19:17       ` Maciej Sobczak
  0 siblings, 1 reply; 10+ messages in thread
From: Robert A Duff @ 2007-07-22 21:44 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> On 22 Lip, 10:08, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>
>> > I would like extend it and do this:
>>
>> > package P is
>> >    type T is record
>> >       V : Integer := Get_Default_Value;
>> >    end record;
>> > private
>> >    function Get_Default_Value return Integer;
>> > end P;
>>
>> > without losing any of the properties of the original solution and
>> > without "leaking" any implementation detail to the public view.
>
>> Yes:
>>
>> package P is
>>    function Get_Default_Value return Integer;
>>    type T is record
>>       V : Integer := Get_Default_Value;
>>    end record;
>> end P;
>
> No, this leaks the implementation detail (the Get_Default function) to
> the public view and pollutes it. I don't want my users to even see it.

I don't see why that's important.  You "leak" the name
Get_Default_Value, but why is that a problem?

You're already leaking the component V.
The fact that clients can say X.V := ...
seems much worse than the fact that they can say
Mumble : Integer := Get_Default_Value.

Why do you want to hide the default value, but expose the component
V itself?

If you want to hide both, then make the type private, and then you can
hide Get_Default_Value also.  Usually a good idea.

> Ada needs real constructors, not just initial values.

I don't get it.  Please explain.

- Bob



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

* Re: Default value for a record component
  2007-07-22 21:44     ` Robert A Duff
@ 2007-07-23 19:17       ` Maciej Sobczak
  2007-07-23 19:41         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: Maciej Sobczak @ 2007-07-23 19:17 UTC (permalink / raw)


On 22 Lip, 23:44, Robert A Duff <bobd...@shell01.TheWorld.com> wrote:

> >> package P is
> >>    function Get_Default_Value return Integer;
> >>    type T is record
> >>       V : Integer := Get_Default_Value;
> >>    end record;
> >> end P;
>
> > No, this leaks the implementation detail (the Get_Default function) to
> > the public view and pollutes it. I don't want my users to even see it.
>
> I don't see why that's important.  You "leak" the name
> Get_Default_Value, but why is that a problem?

Why not have everything in public view then?

This function is not part of the interface. The initial value can be
part of the interface, but not the function. From the client's
perspective there is no function at all - it's existence is only an
artifact of how things are implemented, not something that the users
should be bothered with.

> You're already leaking the component V.

So? Why these should be connected?

> The fact that clients can say X.V := ...
> seems much worse

It doesn't have to be bad at all - after all, Ada allows to have full
record definitions in public view for a reason, right?

> Why do you want to hide the default value, but expose the component
> V itself?

I don't want to hide the default value - after all, the value of this
default value (hm...) is available to the user after the object is
created, so there is nothing to hide.
What I want to hide is the mechanics of where this value comes from.
Or even how often it is computed (hint: the function can be stateful).

> If you want to hide both

The point is I don't.

The C++ version:

class T
{
public:
   T() : V(getDefault()) {}

   int V;

private:
   static int getDefault();
};

(or even I can hide getDefault in the implementation file completely,
without even mentioning it in the class definition)

> > Ada needs real constructors, not just initial values.
>
> I don't get it.  Please explain.

The visibility of a component and the mechanics of computing its
initial value are orthogonal and should not depend on one another. I
can have completely separate reasons to expose or hide either of them.

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




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

* Re: Default value for a record component
  2007-07-23 19:17       ` Maciej Sobczak
@ 2007-07-23 19:41         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2007-07-23 19:41 UTC (permalink / raw)


On Mon, 23 Jul 2007 12:17:46 -0700, Maciej Sobczak wrote:

> On 22 Lip, 23:44, Robert A Duff <bobd...@shell01.TheWorld.com> wrote:
> 
>> If you want to hide both
> 
> The point is I don't.
> 
> The C++ version:
> 
> class T
> {
> public:
>    T() : V(getDefault()) {}
> 
>    int V;
> 
> private:
>    static int getDefault();
> };
> 
> (or even I can hide getDefault in the implementation file completely,
> without even mentioning it in the class definition)
> 
>>> Ada needs real constructors, not just initial values.
>
>> I don't get it.  Please explain.
> 
> The visibility of a component and the mechanics of computing its
> initial value are orthogonal and should not depend on one another. I
> can have completely separate reasons to expose or hide either of them.

(see Jeff Carter's post)

You are barking at a wrong tree. It looks more like an abstract member
interface. So that you could declare that there is an Integer component V
in T, while hiding all stuff about its initialization / finalization /
reading / writing. Parent's construction is only a part of the problem.

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



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

* Re: Default value for a record component
  2007-07-21 21:19 Default value for a record component Maciej Sobczak
  2007-07-22  8:08 ` Dmitry A. Kazakov
@ 2007-07-24  1:27 ` Randy Brukardt
  2007-07-24  9:54   ` Maciej Sobczak
  1 sibling, 1 reply; 10+ messages in thread
From: Randy Brukardt @ 2007-07-24  1:27 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message
news:1185052757.500324.16860@22g2000hsm.googlegroups.com...
...
> without losing any of the properties of the original solution and
> without "leaking" any implementation detail to the public view. The
> idea is, of course, to compute the default value at run-time, each
> time the new object is created - but without touching the general
> "look&feel" of the original code (so that for example Controlled is
> excluded).

This is a rather stupid question, especially given the C++ example that you
give later. The closest analog to a C++ class in Ada is a controlled type.
If you want something like a C++ class, then you are likely to need to use
the tools provided in Ada to get that result.

Your question is very much like asking how to tighten a bolt that holds
together a TV cabinet, but insisting that you will only use a hammer to do
so. When someone says "use a wrench" (controlled type), you say "no, I want
to use a hammer!" (untagged record type). When someone else says "use a
screwdriver" (private part), you say "no, I want to use a hammer!". But a
hammer won't solve your problem (unless perhaps you hit yourself in the head
with it a few times! ;-)

Hinestly, I don't see any sane reason for being unwilling to use a
controlled type here. Virtually all new composite types in Ada ought to be
controlled types, because there is always some reason that you will (now or
in the future) need to have a complex initializer or finalizer. And it's
harder to retrofit that later than right away.

Moreover, the only real difference for controlled in this example is the
syntax used to declare the type; the relevant semantics is essentially
identical (how the component is accessed, objects are created, etc.) Which
means that your only real complaint is that you don't like "controlled" in
the declaration; which is about as silly as saying that Ada doesn't support
OOP because it doesn't have a "class" type.

In any case, having a type that is visible rather than a private type is
almost always a mistake. Yes, Ada allows it, but that's mainly because
methodological restrictions don't belong in a programming language (we've
dropped many of the ones originally present in Ada 83 because they get in
the way in rare but useful cases). And once you allow *anything* to leak
about the implementation of a type, there is no real value in hiding any of
it -- so Ada doesn't really try to provide such possibilities.

                                     Randy.





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

* Re: Default value for a record component
  2007-07-24  1:27 ` Randy Brukardt
@ 2007-07-24  9:54   ` Maciej Sobczak
  2007-07-24 19:12     ` Randy Brukardt
  0 siblings, 1 reply; 10+ messages in thread
From: Maciej Sobczak @ 2007-07-24  9:54 UTC (permalink / raw)


On 24 Lip, 03:27, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> This is a rather stupid question, especially given the C++ example that you
> give later. The closest analog to a C++ class in Ada is a controlled type.

What is the analog of C++ struct with a constructor, then?

> Hinestly, I don't see any sane reason for being unwilling to use a
> controlled type here.

Honestly, me neither. The question is really about the language design
and its ability to express orthogonal concepts. For me field
visibility and its initialization are orthogonal. Well, should be.

This question and my motivation for asking it has absolutely nothing
to do with how I design the actual software, so I take the liberty not
to answer the other parts of your post (the ones with "stupid",
"silly" and "hammer"), which are not really relevant to what I'm
asking.

> In any case, having a type that is visible rather than a private type is
> almost always a mistake.

Can't you think about examples where it isn't? (the "almost always"
part has to be complemented by something)

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




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

* Re: Default value for a record component
  2007-07-24  9:54   ` Maciej Sobczak
@ 2007-07-24 19:12     ` Randy Brukardt
  0 siblings, 0 replies; 10+ messages in thread
From: Randy Brukardt @ 2007-07-24 19:12 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message
news:1185270857.459100.34770@q75g2000hsh.googlegroups.com...
> On 24 Lip, 03:27, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
> > This is a rather stupid question, especially given the C++ example that
you
> > give later. The closest analog to a C++ class in Ada is a controlled
type.
>
> What is the analog of C++ struct with a constructor, then?

A function is a constructor for Ada; declare an appropriate function and use
it.

> > Hinestly, I don't see any sane reason for being unwilling to use a
> > controlled type here.
>
> Honestly, me neither. The question is really about the language design
> and its ability to express orthogonal concepts. For me field
> visibility and its initialization are orthogonal. Well, should be.

Everything in Ada is inter-related; often in ways that are not obvious. I
learned this the hard way when we were trying to subset Ada in the early
1980's. It just didn't work very well because there always was something
else that you needed to have a full solution. Eventually we ended up with
95% of the language, and then we might as well finish the whole thing.

I realize that someone relatively new to Ada might not know this, but you
cannot usefully look at single features of Ada in a vacuum. You need to use
many of them...

...
> > In any case, having a type that is visible rather than a private type is
> > almost always a mistake.
>
> Can't you think about examples where it isn't? (the "almost always"
> part has to be complemented by something)

I know of various examples where it wasn't, but those examples are almost
always motivated more by laziness (don't want to write a function call to
access a component) or by missing features in the language (Dmitry's
"virtual components", some way to write aggregates and literals for private
types, etc.). These two reasons are really the same, because if the missing
features were available, one could write an appropriate private type but
still use it as if it was a visible type. The net effect is that I think
that if we had a "perfect" programming language, there would never be a
reason to declare a visible type, but there might be such a reason given the
imperfect nature of real programming languages. (But even then, you are
likely to regret it.)

                                 Randy.





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

end of thread, other threads:[~2007-07-24 19:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-21 21:19 Default value for a record component Maciej Sobczak
2007-07-22  8:08 ` Dmitry A. Kazakov
2007-07-22 19:44   ` Maciej Sobczak
2007-07-22 21:44     ` Robert A Duff
2007-07-23 19:17       ` Maciej Sobczak
2007-07-23 19:41         ` Dmitry A. Kazakov
2007-07-22 20:01   ` Jeffrey R. Carter
2007-07-24  1:27 ` Randy Brukardt
2007-07-24  9:54   ` Maciej Sobczak
2007-07-24 19:12     ` Randy Brukardt

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