and then... (a curiosity)

This is a discussion on and then... (a curiosity) within the ADA forums in Programming Languages category; Martin Krischik <krischik @ users.sourceforge.net> writes: > Actually it is good example - for both: > > 1) Log to both Disk and Network and return true if at least one was > successful: > > Log_To_Network (Message) or Log_To_Disk (Message) > > 2) Log to Network and if that fails log to Disk and return true if at > least one was successful: > > Log_To_Network (Message) or else Log_To_Disk (Message) > > And it shows nicely the why there are two: The programmer can decide > which behaviour he / she wants. My problem is not with the ...

Go Back   Application Development Forum > Programming Languages > ADA

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #11  
Old 09-01-2008, 01:56 PM
Ray Blaak
Guest
 
Default Re: and then... (a curiosity)

Martin Krischik <krischik@users.sourceforge.net> writes:
> Actually it is good example - for both:
>
> 1) Log to both Disk and Network and return true if at least one was
> successful:
>
> Log_To_Network (Message) or Log_To_Disk (Message)
>
> 2) Log to Network and if that fails log to Disk and return true if at
> least one was successful:
>
> Log_To_Network (Message) or else Log_To_Disk (Message)
>
> And it shows nicely the why there are two: The programmer can decide
> which behaviour he / she wants.


My problem is not with the theoretical elegance as such, but rather that "or"
vs "or else" is not immediately clear to me.

As a multi-language programmer, I am really really used to thinking of boolean
or as "if one is true we don't care about the other". This instinct is
reenforced both from the current popular languages as well as from formal
proof styles in programming methodology.

So, I don't like relying the execution of both disjuncts. Sure, I could use
"or else" consistently, but I like thinking of boolean or as good old regular
boolean or.

So, my preference for the first log example (do both, return success of at
least one is:

declare
Network_Logged : Boolean := Log_To_Network(Message);
Disked_Logged : Boolean := Log_To_Disk(Message);
begin
return Network_Logged or Disked_Logged;
end;

--
Cheers, The Rhythm is around me,
The Rhythm has control.
Ray Blaak The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net The Rhythm has my soul.
Reply With Quote
  #12  
Old 09-01-2008, 11:41 PM
Steve
Guest
 
Default Re: and then... (a curiosity)

"mockturtle" <framefritti@gmail.com> wrote in message
news:18b41828-bda4-4484-8884-ad62ce1c831d@f36g2000hsa.googlegroups.com...
> Dear.all,
> today while I was writing in my favorite language
> (PERL with C extensions, of course :-)))) I wondered why in Ada the
> "shortcut and" is "and then", while the simple "and" has not
> a shortcut behaviour. My curiosity stems from the fact that
> I am not able to envision any situation where the "non shortcut"
> version would preferable, but I immagine that there was some
> reason for this choice. Do anyone have any hint?
>
> Thank you in advance.


There are cases where both arguments to an "and" operator should always be
used. For example if you have Function A and Functon B involved in a
condition:

if A(x) and B(y) then
... do something
end if;

If short circuit evalution is permitted then more complex logic is required
to assure that both arguments are evaluated:

resultA := A(x);
resultB := B(z);
if resultA and resultB then
... do something
end if;

With Ada you can choose whether or not you want short circuit evaluation.
If you require short circuit evaluation you must convey that information to
the compiler. If you do not require short circuit evaluation you can convey
that information as well. The more the compiler knows about your
requirements, the greater the potential for optimization.

The form used also conveys information about the code to programmers reading
the code.

Regards,
Steve


Reply With Quote
  #13  
Old 09-02-2008, 02:53 AM
Martin Krischik
Guest
 
Default Re: and then... (a curiosity)

Ray Blaak schrieb:
> Martin Krischik <krischik@users.sourceforge.net> writes:
>> Actually it is good example - for both:
>>
>> 1) Log to both Disk and Network and return true if at least one was
>> successful:
>>
>> Log_To_Network (Message) or Log_To_Disk (Message)
>>
>> 2) Log to Network and if that fails log to Disk and return true if at
>> least one was successful:
>>
>> Log_To_Network (Message) or else Log_To_Disk (Message)
>>
>> And it shows nicely the why there are two: The programmer can decide
>> which behaviour he / she wants.

>
> My problem is not with the theoretical elegance as such, but rather that "or"
> vs "or else" is not immediately clear to me.




> As a multi-language programmer, I am really really used to thinking of boolean
> or as "if one is true we don't care about the other".


Funny I am not - probably because my first languages where Basic and
Pascal - and Basic and Pascal do not guarantee short cut boolean. Modern
Basic and Pascal dialects might have it but it is not guaranteed in the
language itself.

> This instinct is
> reenforced both from the current popular languages as well as from formal
> proof styles in programming methodology.


When I was at Polytechnic first language was PL/1, second Pascal and
therefore methodology was different. i.E. Don't rely on the execution
order of boolean expressing.

> So, I don't like relying the execution of both disjuncts. Sure, I could use
> "or else" consistently, but I like thinking of boolean or as good old regular
> boolean or.


They are not necessarily both executed with plain old OR and AND either.
Plain old OR and AND leaves all options open to the optimizer: Out of
order execution Common subexpression elimination or dead code elimination.

If the optimizer determines that the 2nd expression has no side effects
it might optimize it away. But note that raising CONSTRAINT_ERROR is a
side effect. So:

if X /= null and x.all = 5 then
Do_Something;
end if;

will most likely become:

if x = null then
raise CONSTRAINT_ERROR;
elif x.all = 5 then
Do_Something;
end if;

Or - for a CPU with hardware null pointer detection - it might become:

if x.all = 5 then
Do_Something;
end if;

Ada is a language which highly rely on the existence of an optimizer.
Unlike the C style languages - the very first C did not have an
optimizer and it still show in the syntax and semantic.- One should
always remember C's main design goal: compiler must fit's into 8 kb of
memory. It explains a lot.

Anyway by default Ada leaves all option options open to the optimizer.
For example:

type Byte is range -128 .. 127;

might not actually be a byte - especially when optimized for
performance. By default all options are open to the optimizer to make
the best of you wish. Only when you start restricting the optimizer with

for Byte'Size use 8;

you are guaranteed an 8 bit type.

You consider this when thinking of "or else" and "and then" - both
restrict the optimizer in it's doing and the result might not be faster.

Regards

Martin
--
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com
Reply With Quote
  #14  
Old 09-02-2008, 03:48 AM
stefan-lucks@see-the.signature
Guest
 
Default Re: and then... (a curiosity)

On Mon, 1 Sep 2008, Steve wrote:
> If short circuit evalution is permitted then more complex logic is required
> to assure that both arguments are evaluated:
>
> resultA := A(x);
> resultB := B(z);
> if resultA and resultB then
> ... do something
> end if;


If I actually require to run both functions A and B, I always write
something like the above (typically inside a declare ... begin ... end),
because I think that makes my intention clearer than by just writing
"and" (or "or").

> With Ada you can choose whether or not you want short circuit evaluation.
> If you require short circuit evaluation you must convey that information to
> the compiler. If you do not require short circuit evaluation you can convey
> that information as well. The more the compiler knows about your
> requirements, the greater the potential for optimization.


True. But the case that you want both expressions to be evaluated is a
rare exception. On a *logic* level, "A and B" implies "if A is false, the
result is false, regardless of B". So short-circuit evaluation is a
natural and good thing for a programming language, and it is regrettable
that Ada needs a more complex syntax for this. (Well, "A and B" also
implies "if B is false, don't care about A", but in a programming language
you can't have it both ways.)

But, as others pointed it: IF the default "and" supported
short-circuit-evaluation, THEN this "and" could not be an ordinary Ada
operator. At the language semantic level, it is much more reasonable to
treat "and" like any other operator or function, such as "+" and "-". So
the inventors of Ada decided on a special syntax for short-circuit
evaluation. But I wish Ada would support some sort of lazy evaluation for
subprogram arguments.

So long

Stefan

--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
  #15  
Old 09-02-2008, 04:57 AM
Martin Krischik
Guest
 
Default Re: and then... (a curiosity)

stefan-lucks@see-the.signature schrieb:

> True. But the case that you want both expressions to be evaluated is a
> rare exception. On a *logic* level, "A and B" implies "if A is false, the
> result is false, regardless of B". So short-circuit evaluation is a
> natural and good thing for a programming language, and it is regrettable
> that Ada needs a more complex syntax for this.


That's not what I learned in my boolean arithmetic classes.

> (Well, "A and B" also
> implies "if B is false, don't care about A", but in a programming language
> you can't have it both ways.)


That is what I learned in my boolean arithmetic classes. It's either
way. There is no preference that the left parameter if more important
then the right. A Human seeing "A∧0" won't evaluate A. And if you see
"f(x)∧g" you would probably evaluate g first as a variable is usually
easier to evaluate then a function.

And it is what you have in Ada - with plain old "and" and "or" the
optimizer is free to do out of order evaluation and dead code
elimination which could well lead to B being evaluated first and A being
optimized away if B already determines the final result.

This - of course - only if the compiler can also determine that A and B
have no side effect. Side effect are that little difference between
arithmetic and programming. The CONSTRAINT_ERROR in:

if X /= null and x.all = 5 then
Do_Something;
end if;

or the global variable which f(x) might change:

function f(x:Integer) is
begin
if x > 10 then
g = false;
end if;
return x > 5;
end f;

It's all about those side effect which make order of evaluation so
important. Otherwise it should not matter.

Note that once you add:

pragma Inline (f);

to the example above things become very interesting for the optimizer
;-) (do remember that the optimizer will use goto without shame).

> But, as others pointed it: IF the default "and" supported
> short-circuit-evaluation, THEN this "and" could not be an ordinary Ada
> operator. At the language semantic level, it is much more reasonable to
> treat "and" like any other operator or function, such as "+" and "-".


Well again, in my arithmetic classes I learned that a+b is the same and
b+a - which includes that the order of evaluation is of no importance.
If you want that ∧ operates the same way as + then "a∧b" must be the
same as "b∧a".

Martin

--
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com
Reply With Quote
  #16  
Old 09-02-2008, 06:33 AM
Ludovic Brenta
Guest
 
Default Re: and then... (a curiosity)

stefan-lu...@see-the.signature wrote:
> True. But, at the logic level, the Ada-statement
>
> if (X >= A'First) and (X <= A'Last) and (A[X]=Y) then
> ...
> else
> ...
> end if;
>
> should *not* raise a Constraint_Error if X < A'First or X > A'Last, but
> instead handle the "else" case.


Except that X may be a function returning a different value for each
call!

> True enough, at the logic level the same should hold for
>
> if (A(x)=Y) and (X >= A'First) and (X <= A'Last) then ... end if;
>
> > It's all about those side effect which make order of evaluation so
> > important. Otherwise it should not matter.

>
> The bad thing is that Constraint_Error counts as a valid side effect here.


And what would be an "invalid" side effect?

> Ideally, the program should check the other branches of the "and"
> expression, and only propagate the exception if none of them evaluates to
> false without raising an exception of its own.


No, because the Constraint_Error (or other exception, or other side
effect such as logging, assignment to a variable, etc.) may be
intentional! The compiler does not and should not try to read your
mind. At least I would find it very disturbing to program in a
language that would try to "do what I mean, not what I say".

> Consider a programm fragment like
>
> if X and Y then
> ...
> end if
>
> Assume Y raises a Constraint_Error if X is false. This appears to be a
> common bug pattern in Ada. I have seen this several times in Ada
> sourcecode, and *never* it was the programmer's intention to raise an
> exception if X is false ... except when an exception was raised
> explicitely in the else branch. Even then, the programmers typically
> expected the exception they raised there, not Constraint_Error.


I have seen this bug a couple of times and always concluded it was
*my* fault and that I should have used "and then" to specify that the
order of evaluation was important. In such situation the mathematical
"and" (where "X and Y" is strictly equivalent to "Y and X") is not
what I want.

I definitely like the fact that Ada gives me the choice (short-circuit
or full evaluation) and the means ("and" vs. "and then") to express my
intent exactly.

--
Ludovic Brenta.

Reply With Quote
  #17  
Old 09-02-2008, 06:50 AM
stefan-lucks@see-the.signature
Guest
 
Default Re: and then... (a curiosity)

> > (Well, "A and B" also
> > implies "if B is false, don't care about A", but in a programming language
> > you can't have it both ways.)

>
> That is what I learned in my boolean arithmetic classes. It's either
> way. There is no preference that the left parameter if more important
> then the right. A Human seeing "A∧0" won't evaluate A. And if you see
> "f(x)∧g" you would probably evaluate g first as a variable is usually
> easier to evaluate then a function.


True. But, at the logic level, the Ada-statement

if (X >= A'First) and (X <= A'Last) and (A[X]=Y) then
...
else
...
end if;

should *not* raise a Constraint_Error if X < A'First or X > A'Last, but
instead handle the "else" case.

True enough, at the logic level the same should hold for

if (A(x)=Y) and (X >= A'First) and (X <= A'Last) then ... end if;

> It's all about those side effect which make order of evaluation so
> important. Otherwise it should not matter.


The bad thing is that Constraint_Error counts as a valid side effect here.

Ideally, the program should check the other branches of the "and"
expression, and only propagate the exception if none of them evaluates to
false without raising an exception of its own.

Consider a programm fragment like

if X and Y then
...
end if

Assume Y raises a Constraint_Error if X is false. This appears to be a
common bug pattern in Ada. I have seen this several times in Ada
sourcecode, and *never* it was the programmer's intention to raise an
exception if X is false ... except when an exception was raised
explicitely in the else branch. Even then, the programmers typically
expected the exception they raised there, not Constraint_Error.

I admit, we will not get this "ideal" behavoiur in any usable programming
language. What happens, e.g., if two different exceptions are raised when
evaluating "A and B"? Which exception should be propagated?

In the absence of this "ideal" behaviour, a short-circuit behaviour of
"and" and "or" would eliminate a common bug pattern in Ada. I would
consider it the lesser evil, compared to the current situation.

> Note that once you add:
>
> pragma Inline (f);
>
> to the example above things become very interesting for the optimizer
> ;-) (do remember that the optimizer will use goto without shame).


Funny idea! ;-)

But at the end, there are lots of gotos ("jumps", "branches") in assembler
code, with or without pragma inline or optimisation.


--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
  #18  
Old 09-02-2008, 08:53 AM
Ludovic Brenta
Guest
 
Default Re: and then... (a curiosity)

> But do you really dispute that following the mathematical conventions
> as much as possible would improve readability?


Of course not. That's wgy "and" should have its mathematical meaning -
i.e it should not impose an order of evaluation and it should not
avoid evaluating its operands. That's what "and then" is for.

> A short-circuit "and" (instead of "and then") would not remove that choice
> -- see the "much better style" above.


But it would break the mathematical purity of "and".

--
Ludovic Brenta.
Reply With Quote
  #19  
Old 09-02-2008, 09:32 AM
stefan-lucks@see-the.signature
Guest
 
Default Re: and then... (a curiosity)

On Tue, 2 Sep 2008, Ludovic Brenta wrote:

> stefan-lu...@see-the.signature wrote:
> > if (X >= A'First) and (X <= A'Last) and (A[X]=Y) then
> > ...
> > else
> > ...
> > end if;
> >
> > should *not* raise a Constraint_Error if X < A'First or X > A'Last, but
> > instead handle the "else" case.

>
> Except that X may be a function returning a different value for each
> call!


On the level of formal logic, there isn't really space for side effects.

> > The bad thing is that Constraint_Error counts as a valid side effect here.

>
> And what would be an "invalid" side effect?


A "valid" side effect would, e.g., be changing a global variable. On the
other hand, a function which raises an exception is essentially a function
returning some value outside its domain (but inside an extended domain).
This isn't quite like a side-effect -- only Ada pretends it is.

> > Ideally, the program should check the other branches of the "and"
> > expression, and only propagate the exception if none of them evaluates to
> > false without raising an exception of its own.

>
> No, because the Constraint_Error (or other exception, or other side
> effect such as logging, assignment to a variable, etc.) may be
> intentional! The compiler does not and should not try to read your
> mind. At least I would find it very disturbing to program in a
> language that would try to "do what I mean, not what I say".


Well, if the program requirements are that the side effects for A and B
actually occur, I consider it poor programming style if people just write

if A(X) and B(Y) then ... end if;

IMHO, much better style is the following:

declare
Tmp_A: Boolean := A(X);
Tmp_B: Boolean := B(X);
begin
if Tmp_A and Tmp_B then ... end if;
end;

This makes the programmers intention clear, "if A(X) and B(X)" doesn't.

> > Consider a programm fragment like
> >
> > if X and Y then
> > ...
> > end if
> >
> > Assume Y raises a Constraint_Error if X is false. This appears to be a
> > common bug pattern in Ada.

[...]
> I have seen this bug a couple of times and always concluded it was
> *my* fault and that I should have used "and then" to specify that the
> order of evaluation was important. In such situation the mathematical
> "and" (where "X and Y" is strictly equivalent to "Y and X") is not
> what I want.


Right!

But do you really dispute that following the mathematical conventions
as much as possible would improve readability?

> I definitely like the fact that Ada gives me the choice (short-circuit
> or full evaluation) and the means ("and" vs. "and then") to express my
> intent exactly.


A short-circuit "and" (instead of "and then") would not remove that choice
-- see the "much better style" above.

In any case, instead of an explicit syntax for short-circuit "and" an
explict syntax for the rare non-short-circuit cases would be preferable,
perhaps "if A(X) and all B(Y) then ... end if;".




--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
  #20  
Old 09-02-2008, 09:39 AM
stefan-lucks@see-the.signature
Guest
 
Default Re: and then... (a curiosity)

> > And what would be an "invalid" side effect?
>
> A "valid" side effect would, e.g., be changing a global variable. On the
> other hand, a function which raises an exception is essentially a function
> returning some value outside its domain (but inside an extended domain).
> This isn't quite like a side-effect -- only Ada pretends it is.


To be clear, if "function F(...) return Boolean" may raise an exception,
such as Constrained_Error, we essentially have a three-valued logic -- the
function can return

- either "true2,
- or "false2,
- or raise an exception, which is tantamount to returning
"undefined".



--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 09:24 PM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.