comp.lang.ada
 help / color / mirror / Atom feed
* Why should the value for a discriminant be static?
@ 2005-02-09 14:30 Jacob Sparre Andersen
  2005-02-09 18:34 ` Randy Brukardt
  0 siblings, 1 reply; 8+ messages in thread
From: Jacob Sparre Andersen @ 2005-02-09 14:30 UTC (permalink / raw)


Occasionally I run into the limitation that the value for a
discriminant be static.  I can design my way around the limitation
(when I remember it), but I would like to know the reason.  (also
because it might make it easier for me to remember the rule)

Greetings,

Jacob
-- 
�You have to blow things up to get anything useful.�
                                  -- Archchancellor Ridcully




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

* Re: Why should the value for a discriminant be static?
  2005-02-09 14:30 Why should the value for a discriminant be static? Jacob Sparre Andersen
@ 2005-02-09 18:34 ` Randy Brukardt
  2005-02-09 20:16   ` Niklas Holsti
  2005-02-09 22:22   ` Jacob Sparre Andersen
  0 siblings, 2 replies; 8+ messages in thread
From: Randy Brukardt @ 2005-02-09 18:34 UTC (permalink / raw)


"Jacob Sparre Andersen" <sparre@nbi.dk> wrote in message
news:rlszmyd956d.fsf@jacob.crs4.it...
> Occasionally I run into the limitation that the value for a
> discriminant be static.  I can design my way around the limitation
> (when I remember it), but I would like to know the reason.  (also
> because it might make it easier for me to remember the rule)

The only place I know of off-hand where there is such a limitation is with
aggregates. There, the limitation is necessary so that compiler can know the
set of components for the aggregate. Otherwise, it would be impossible to
check that components are given, which is *the* major benefit of using an
aggregate over a series of component assignments.

I suppose such a check could be done at runtime, but that would be
substantially less safe, as errors could exist in a program for a long time
and occur only in unusual conditions after deployment.

Anyway, does that answer your question, or was this in some other context?

                 Randy Brukardt







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

* Re: Why should the value for a discriminant be static?
  2005-02-09 18:34 ` Randy Brukardt
@ 2005-02-09 20:16   ` Niklas Holsti
  2005-02-10  0:19     ` Jeffrey Carter
  2005-02-09 22:22   ` Jacob Sparre Andersen
  1 sibling, 1 reply; 8+ messages in thread
From: Niklas Holsti @ 2005-02-09 20:16 UTC (permalink / raw)


Randy Brukardt wrote:
> "Jacob Sparre Andersen" <sparre@nbi.dk> wrote in message
> news:rlszmyd956d.fsf@jacob.crs4.it...
> 
>>Occasionally I run into the limitation that the value for a
>>discriminant be static.  I can design my way around the limitation
>>(when I remember it), but I would like to know the reason.  (also
>>because it might make it easier for me to remember the rule)
> 
> 
> The only place I know of off-hand where there is such a limitation is with
> aggregates. There, the limitation is necessary so that compiler can know the
> set of components for the aggregate. Otherwise, it would be impossible to
> check that components are given, which is *the* major benefit of using an
> aggregate over a series of component assignments.
> 
> I suppose such a check could be done at runtime, but that would be
> substantially less safe, as errors could exist in a program for a long time
> and occur only in unusual conditions after deployment.

I agree with the safety advantages of the static rule, but I have often 
wished that an aggregate would allow an expression with a statically 
known subtype as the discriminant *when* this subtype uniquely 
determines the set of components. For example:

    type Days is (
       Monday, Tuesday, Wednesday, Thursday, Friday,
       Saturday, Sunday);

    subtype Busy_Days is Days range Monday .. Friday;
    subtype Idle_Days is Days range Saturday .. Sunday;

    type Activity (Day : Days) is record
       case Day is
       when Busy_Days => Work : Work_Type;
       when Idle_Days => Play : Play_Type;
       end case;
    end record;

(I know this is unlike reality, where some of us work on week-ends, but 
this is just an example :-) I would like to be able to write an 
aggregate with the discriminant given by a non-static expression of a 
statically known subtype, for example:

    function Do_A_Job (Today : Busy_Days; Job : Work_Type)
    return Activity
    is
    begin

       -- NOT ALLOWED NOW:

       return (
          Day  => Today, -- Statically known to be in Busy_Days,
          Work => Job);  -- therefore this component exists.

    end Do_A_Job;

If, instead, the Today parameter is "Today : Days", I would like to be 
able to write the same aggregate with a conversion:

       -- NOT ALLOWED NOW:

       return (
          Day  => Busy_Days (Today),
          Work => Job);

This would include a run-time check that Today is in Busy_Days.

Would this be horribly messy to implement? The latter form with a 
conversion seems quite unambiguous. Without a conversion the 
discriminant expression should perhaps be required to be just a 
"statically constrained object" as defined in LRM 4.9(32).


-- 
Niklas Holsti
Tidorum Ltd

niklas holsti tidorum fi
       .      @       .




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

* Re: Why should the value for a discriminant be static?
  2005-02-09 18:34 ` Randy Brukardt
  2005-02-09 20:16   ` Niklas Holsti
@ 2005-02-09 22:22   ` Jacob Sparre Andersen
  1 sibling, 0 replies; 8+ messages in thread
From: Jacob Sparre Andersen @ 2005-02-09 22:22 UTC (permalink / raw)


Randy Brukardt <randy@rrsoftware.com> writes:
> Jacob Sparre Andersen <sparre@nbi.dk> wrote in message
> news:rlszmyd956d.fsf@jacob.crs4.it...

> > Occasionally I run into the limitation that the value for a
> > discriminant be static.  I can design my way around the limitation
> > (when I remember it), but I would like to know the reason.  (also
> > because it might make it easier for me to remember the rule)
> 
> The only place I know of off-hand where there is such a limitation
> is with aggregates.

Yes.  That was also what I ran into today.

> There, the limitation is necessary so that compiler can know the set
> of components for the aggregate.

That makes sense.

> Otherwise, it would be impossible to check that components are
> given, which is *the* major benefit of using an aggregate over a
> series of component assignments.

Yes.

> I suppose such a check could be done at runtime, but that would be
> substantially less safe, as errors could exist in a program for a
> long time and occur only in unusual conditions after deployment.

True.  And although I think I also had the record components correct
the first time around (except for the non-static discriminant), the
changed code is probably safer.

> Anyway, does that answer your question, or was this in some other
> context?

It answers my question.  And I think it is enough to make me remember
this rule in the future.  Thanks.

Jacob
-- 
�By becoming continuous, war has fundamentally changed its character.
 In past ages, a war, almost by definition, was something that sooner
 or later came to an end, usually in unmistakable victory or defeat.�
                               -- Nineteen Eighty-Four, George Orwell
�I don't think you can win [the war on terror].�    -- George W. Bush



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

* Re: Why should the value for a discriminant be static?
  2005-02-09 20:16   ` Niklas Holsti
@ 2005-02-10  0:19     ` Jeffrey Carter
  2005-02-10 13:11       ` Niklas Holsti
  0 siblings, 1 reply; 8+ messages in thread
From: Jeffrey Carter @ 2005-02-10  0:19 UTC (permalink / raw)


Niklas Holsti wrote:

> I agree with the safety advantages of the static rule, but I have often 
> wished that an aggregate would allow an expression with a statically 
> known subtype as the discriminant *when* this subtype uniquely 
> determines the set of components. For example:
> 
>    type Days is (
>       Monday, Tuesday, Wednesday, Thursday, Friday,
>       Saturday, Sunday);
> 
>    subtype Busy_Days is Days range Monday .. Friday;
>    subtype Idle_Days is Days range Saturday .. Sunday;
> 
>    type Activity (Day : Days) is record
>       case Day is
>       when Busy_Days => Work : Work_Type;
>       when Idle_Days => Play : Play_Type;
>       end case;
>    end record;
> 
>    function Do_A_Job (Today : Busy_Days; Job : Work_Type)
>    return Activity
>    is
>    begin
>       return (
>          Day  => Today, -- Statically known to be in Busy_Days,
>          Work => Job);  -- therefore this component exists.
>    end Do_A_Job;

In simple terms, this design if faulty. It's easy to argue otherwise for 
this simple example (7 enumeration values and 2 variants), but I've seen 
real world examples where it's harder to argue this way. One had over 
200 enumeration values and about 10 variants.

I argued in that case that they really needed 11 types: and enumeration 
type for the discriminant with about 10 values, and 10 other types, one 
for each variant to contain the specific information for the variant. 
That level of code modification was considered unacceptable, so I 
pointed them to the local result variable alternative:

function F (Day : Busy_Days; Work : Works)
return Activities -- Let's use a consistent naming policy :)
is
    Result : Activities (Day => Day);
begin -- F
    Result.Work := Work;
    return Result;
end F;

Of course, they really had a parameter of type Days, and had to build 
results for every variant, for much larger variants, so this got pretty 
hairy.

For your particular example, I would always recommend a type for the 
discriminant:

type Day_Kind_ID is (Busy_Day, Idle_Day);

You could have 2 types for the actual day in question, or a single type 
with 2 subtypes; to differ from your example as much as possible, let's 
choose the former:

type Busy_Day_Name is (Monday, Tuesday, Wednesday, Thursday, Friday);
type Idle_Day_Name is (Saturday, Sunday);

type Activity_Info (Day_Kind : Day_Kind_ID) is record
    case Day_Kind is
    when Busy_Day =>
       Work_Day : Busy_Day_Name;
       Work     : Work_Info;
    when Idle_Day =>
       Play_Day : Idle_Day_Name;
       Play     : Play_Info;
    end case;
end record;

Then your function would be

function F (Day : Busy_Day_Name; Work : Work_Info) return Activity_Info
is
    -- null;
begin -- F
    return Activity_Info'(Day_Kind => Busy_Day, -- Static.
                          Work_Day => Day,
                          Work     => Work);
end F;

-- 
Jeff Carter
"My mind is aglow with whirling, transient nodes of
thought, careening through a cosmic vapor of invention."
Blazing Saddles
85



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

* Re: Why should the value for a discriminant be static?
  2005-02-10  0:19     ` Jeffrey Carter
@ 2005-02-10 13:11       ` Niklas Holsti
  2005-02-11  1:40         ` Jeffrey Carter
  0 siblings, 1 reply; 8+ messages in thread
From: Niklas Holsti @ 2005-02-10 13:11 UTC (permalink / raw)


Jeffrey Carter wrote:
> Niklas Holsti wrote:
> 
>> I agree with the safety advantages of the static rule, but I have 
>> often wished that an aggregate would allow an expression with a 
>> statically known subtype as the discriminant *when* this subtype 
>> uniquely determines the set of components. For example:
>>
>>    type Days is (
>>       Monday, Tuesday, Wednesday, Thursday, Friday,
>>       Saturday, Sunday);
>>
>>    subtype Busy_Days is Days range Monday .. Friday;
>>    subtype Idle_Days is Days range Saturday .. Sunday;
>>
>>    type Activity (Day : Days) is record
>>       case Day is
>>       when Busy_Days => Work : Work_Type;
>>       when Idle_Days => Play : Play_Type;
>>       end case;
>>    end record;
>>
>>    function Do_A_Job (Today : Busy_Days; Job : Work_Type)
>>    return Activity
>>    is
>>    begin
>>       return (
>>          Day  => Today, -- Statically known to be in Busy_Days,
>>          Work => Job);  -- therefore this component exists.
>>    end Do_A_Job;
> 
> 
> In simple terms, this design if faulty.

Now then, that's rather harsh. It's certainly legal Ada; if you think
its philosophically faulty, you are entitled to your opinion and I am
entitled to disagree; if you think its faulty because it leads to
practical problems, the problem is just with the requirement for
static discriminants in aggregates -- which is what this thread is
about.

> It's easy to argue otherwise for 
> this simple example (7 enumeration values and 2 variants), but I've seen 
> real world examples where it's harder to argue this way. One had over 
> 200 enumeration values and about 10 variants.
> 
> I argued in that case that they really needed 11 types: and enumeration 
> type for the discriminant with about 10 values, and 10 other types, one 
> for each variant to contain the specific information for the variant.

That is of course the work-around. I have done designs both ways 
depending on the circumstances.

> That level of code modification was considered unacceptable, so I 
> pointed them to the local result variable alternative:
> 
> function F (Day : Busy_Days; Work : Works)
> return Activities -- Let's use a consistent naming policy :)

(In my own code I consistently use the suffix _T for types.)

> is
>    Result : Activities (Day => Day);
> begin -- F
>    Result.Work := Work;
>    return Result;
> end F;

Which loses the compile-check that the assigned components exist
and that all existing components are assigned. This is what I
(and others) want to avoid. Of course it can be an emergency
solution as in your anecdote.

The question is one of symmetry: since the language allows static
subtypes in the declaration of the variant parts of a record type,
it should symmetrically allow statically subtyped expressions as
discriminant values in aggregates for such record types.


-- 
Niklas Holsti
Tidorum Ltd

niklas holsti tidorum fi
       .      @       .




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

* Re: Why should the value for a discriminant be static?
  2005-02-10 13:11       ` Niklas Holsti
@ 2005-02-11  1:40         ` Jeffrey Carter
  2005-02-11  7:52           ` Niklas Holsti
  0 siblings, 1 reply; 8+ messages in thread
From: Jeffrey Carter @ 2005-02-11  1:40 UTC (permalink / raw)


Niklas Holsti wrote:

> Now then, that's rather harsh. It's certainly legal Ada; if you think
> its philosophically faulty, you are entitled to your opinion and I am
> entitled to disagree; if you think its faulty because it leads to
> practical problems, the problem is just with the requirement for
> static discriminants in aggregates -- which is what this thread is
> about.

Not at all. There's a software engineering principle that one thing 
should serve one purpose, and this violates that: it serves both to 
identify the 2 classes and to provide the specific information for each 
class.

> Which loses the compile-check that the assigned components exist
> and that all existing components are assigned. This is what I
> (and others) want to avoid. Of course it can be an emergency
> solution as in your anecdote.

The compile-time check exists at the point of the call to the function 
in this case, but in the general case that doesn't hold. On the other 
hand, when designed properly, you do get the compile time check.

> The question is one of symmetry: since the language allows static
> subtypes in the declaration of the variant parts of a record type,
> it should symmetrically allow statically subtyped expressions as
> discriminant values in aggregates for such record types.

So, I guess the language must be faulty to allow static subtypes for 
variants.

-- 
Jeff Carter
"I spun around, and there I was, face to face with a
six-year-old kid. Well, I just threw my guns down and
walked away. Little bastard shot me in the ass."
Blazing Saddles
40



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

* Re: Why should the value for a discriminant be static?
  2005-02-11  1:40         ` Jeffrey Carter
@ 2005-02-11  7:52           ` Niklas Holsti
  0 siblings, 0 replies; 8+ messages in thread
From: Niklas Holsti @ 2005-02-11  7:52 UTC (permalink / raw)


Jeffrey Carter wrote:
> Niklas Holsti wrote:
> 
>> Now then, that's rather harsh. It's certainly legal Ada; if you think
>> its philosophically faulty, you are entitled to your opinion and I am
>> entitled to disagree; if you think its faulty because it leads to
>> practical problems, the problem is just with the requirement for
>> static discriminants in aggregates -- which is what this thread is
>> about.
> 
> 
> Not at all. There's a software engineering principle that one thing 
> should serve one purpose, and this violates that: it serves both to 
> identify the 2 classes and to provide the specific information for each 
> class.

So the "fault" is philosophical. From your interpretation of that
principle, you could argue against any use of "derived properties
of objects", and insist on a separate component to hold each such
derived property. Not attractive to me, but as I said, we can
disagree on what is desirable, even if we agree that the current
Ada rules are asymmetrical in this area.


-- 
Niklas Holsti
Tidorum Ltd

niklas holsti tidorum fi
       .      @       .




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

end of thread, other threads:[~2005-02-11  7:52 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-09 14:30 Why should the value for a discriminant be static? Jacob Sparre Andersen
2005-02-09 18:34 ` Randy Brukardt
2005-02-09 20:16   ` Niklas Holsti
2005-02-10  0:19     ` Jeffrey Carter
2005-02-10 13:11       ` Niklas Holsti
2005-02-11  1:40         ` Jeffrey Carter
2005-02-11  7:52           ` Niklas Holsti
2005-02-09 22:22   ` Jacob Sparre Andersen

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