comp.lang.ada
 help / color / mirror / Atom feed
* Side-Effects in Functions [Rosen Trick]
  2001-11-04 13:07                   ` Robert Dewar
@ 2001-11-04 17:17                     ` Nick Roberts
  2001-11-05  2:46                       ` Robert Dewar
  0 siblings, 1 reply; 28+ messages in thread
From: Nick Roberts @ 2001-11-04 17:17 UTC (permalink / raw)


"Robert Dewar" <dewar@gnat.com> wrote in message
news:5ee5b646.0111040507.5ca7ea23@posting.google.com...
> "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message
news:<9s230d$107b5a$2@ID-25716.news.dfncis.de>...
>
> > PS: Why? Because functions should not have side-effects (in a language
like
> > Ada).
>
> You present this as a kind of obvious ab initio fact, but
> it is nothing of the kind.

I was hoping that it would be obvious that I was putting this point in a
deliberately polemical style. I am merely stating my own strongly held
belief on this subject, based on perfectly good reasoning, as well as the
consensus of programming wisdom.

> Here are the facts:
> ...
> There was some attept early on to consider trying to stop
> functions from having side effects, and indeed I think one
> published early version of Ada distinguished functions and
> value returning procedures, or at least that was discussed.

I'm glad this didn't happen, because, as mentioned in my previous post,
there are occasions -- such as debugging, profiling, auditing -- when it is
useful for a function to have a side-effect, and forcing the programmer to
convert it to a procedure -- and thus all calls on it to procedure calls --
would be wholly unjustified.

> But such attempts were firmly rejected, and the decision
> was that there are situations where it makes perfectly good
> sense for functions to have side effects, and an absolute
> rule prohibiting them is in the same not-well-thought-out
> category as absolute rules against use clauses, goto statements,
> unchecked conversion, and various other very
> useful features of Ada. Useful does not mean that they should be used
> all the time, or misused, just that they have some legitimate use.

I agree there.

> Another important factor is that other languages agree with
> Ada that functions should be allowed to have side effects.
> In particular C takes this viewpoint, and side effects in
> functions are common in C, including side effects in calls
> to standard functions in the C library.

The fact that the C language permits something, or that C programmers do a
particular thing, is surely no recommendation that Ada programmers should do
the same!

> Now in Ada, the rule for functions is a bit odd:
>
>   Side effects from access to global variables - permitted
>   Side effects from modifying access type args - permitted
>   Side effects from in out parameters - prohibited

These rules may seem a little odd, but they pertain to what Ada allows
programmers to do, not what Ada programmers should do. My point was entirely
about what Ada programmers should do.

> I have never understood the rationale for this inconsistent
> design.

The rationale is simple and well-known Robert! Good grief, every Ada
textbook on the planet has an example of how side-effects in functions can
introduce subtle and pernicious bugs (especially on porting). Must I really
repeat these?

> Most annoyingly, the natural translation of a * arg in a
> C function, e.g. *int, is to translate it to an IN OUT
> parameter, but that is arbitrarily not allowed.

This isn't the most natural translation, and the prevention of the use of
in-out parameters in functions is not arbitrary, it was, as you said
earlier, carefully debated.

> It is of
> course allowed to translate it to an access-to-int parameter, since
> there is no restriction on the use of
> such parameters for functions, even though they are obviously
> logically equivalent from an expressive point of view.

They are not logically equivalent. The use of the access parameter implies
the (actual) object is aliased (kept in memory essentially all the time).
This may be something that C assumes for all its variables (clever compiler
deductions notwithstanding), but Ada does not, and rightly so.

> The trouble is that although in-out parameters and access-type-to-foo
> parameters are equivalent from a logical
> point of view, they are very different syntactically, and
> we are left with the following unpleasant alternatives in
> interfacing to C functions:
>
>   1. Interface as procedures. This either requires a
>      wrapper or something like the Valued_Procedure
>      interface available in GNAT. The trouble with
>      this is that the calls get really ugly. Yes, in
>      the case where the result is just an error code
>      it's acceptable, but that's by no means always
>      the case.
>
>   2. Interface using named access types. The calls are
>      somewhat better here, but you get a plague of aliased
>      variables appearing, and the access types need
>      defining which is messy.
>
>   3. Use a wrapper with global variables for the missing
>      parameters. But this is nasty anyway, and gets too
>      far from the C form.

To me, it is obvious that option 2 should be used. To describe the required
aliasing of variables as a 'plague' is rather an overstatement: it simply
means adding the word 'aliased' to the appropriate objects; that's not a
plague! It is absolutely right, since they must (at least in effect) be
aliased for the called C routine(s) to access them via a pointer.

> To me, the arguments for allowing IN OUT parameters, at
> least for interfaced functions, are very strong, but
> unfortunately, this is an argument that cannot be won.
> There seem to be three kinds of people:
>
> 1. Those who are adamantly opposed to IN OUT parameters
> on basically religeous (i.e. belief based) grounds without
> very strong technical justification in many cases, or with
> the technical justification being inconsistent with the
> general permission for functions to have side effects in
> Ada. This is a surprisingly large group.

Well, as I say above, there is indeed a very strong, very well documented,
and generally accepted technical justification for avoiding side-effects in
functions (which is the point I was originally making), and disallowing
in-out parameters in Ada functions seems to be be perfectly in tune with
this principle.

> ...

To sum up, I am amazed at Robert's opposition to what I have always
understood to be a very well established programming principle (in
procedural languages such as Ada). That principle is taught for very good
software engineering reasons. I said "Must I really repeat these?". If the
answer is simply "Yes.", then please just answer "Yes" and I will.

--
Nick Roberts






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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-04 17:17                     ` Side-Effects in Functions [Rosen Trick] Nick Roberts
@ 2001-11-05  2:46                       ` Robert Dewar
  2001-11-05  7:26                         ` pete
                                           ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Robert Dewar @ 2001-11-05  2:46 UTC (permalink / raw)


"Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9s3tl3$111hco$1@ID-25716.news.dfncis.de>...
> I was hoping that it would be obvious that I was putting 
> this point in a
> deliberately polemical style. I am merely stating my own 
> strongly held
> belief on this subject, based on perfectly good 
> reasoning, as well as the
> consensus of programming wisdom.

No, this is by no means a consensus. Most procedural
languages, including Ada, allow functions to have side
effects. And on the narrower issue of allowing IN OUT
parameters in functions, there is nothing like a consensus
opposing this. Indeed my guess is that during the design
phase on Ada 95, if a show down had been insisted on, 
the side favoring IN OUT parameters would have (narrowly)
won, but it seemed inappropriate to force this change in
the absence of a consensus on the other side. So your
understanding of the consensus here is completely wrong.

> > Now in Ada, the rule for functions is a bit odd:
> >
> >   Side effects from access to global variables - permitted
> >   Side effects from modifying access type args - permitted
> >   Side effects from in out parameters - prohibited
> 
> These rules may seem a little odd, but they pertain to what Ada allows
> programmers to do, not what Ada programmers should do. My point was entirely
> about what Ada programmers should do.

Features in Ada are there to be used, anyone who announces
that some feature should never be used probably just does
not understand the issues. Of course they should not be
abused.

> The rationale is simple and well-known Robert! Good grief, every Ada
> textbook on the planet has an example of how side-effects in functions can
> introduce subtle and pernicious bugs (especially on porting). Must I really
> repeat these?

Please don't! Many people would say EXACTLY the same
about assignments, or global variables. Of course this
feature can be misused, as can many features. Forbidding
something because it can be misused is an absurd design
approach and one that fortunately Ada seldom indulges in.

> > Most annoyingly, the natural translation of a * arg in a
> > C function, e.g. *int, is to translate it to an IN OUT
> > parameter, but that is arbitrarily not allowed.
> 
> This isn't the most natural translation, and the prevention of the use of
> in-out parameters in functions is not arbitrary, it was, as you said
> earlier, carefully debated.

Actually the issue of IN OUT parameters was never carefully
debated. It was clear early on that it was one of these
religeous issues (note Nick's odd use of the phrase "strong
belief") which was not something that could be calmly debated (your
"good grief" shows this nicely -- why people
get so excercised over this issue is a puzzle to me).


> To me, it is obvious that option 2 should be used. To describe the required
> aliasing of variables as a 'plague' is rather an overstatement: it simply
> means adding the word 'aliased' to the appropriate objects; that's not a
> plague! It is absolutely right, since they must (at least in effect) be
> aliased for the called C routine(s) to access them via a pointer.

Most people feel that being forced to add aliased keywords
all over the place, just because of odd interfacing requirements for C
functions, is unfortunate. If you find
it perfectly fine to have aliased keywords around, fine,
but you obviously don't have the alergy to aliasing that
many people have. It is not accidental that aliased is not
the default.


> To sum up, I am amazed at Robert's opposition to what I
> have always understood to be a very well established 
> programming principle (in procedural languages such as 
> Ada).

No wonder if you are amazed if you think this is a "very
well established programming principle". That's just wrong.
As I noted earlier, nearly all procedural languages DO
allow side effects in functions.

And of course Ada does too (allow side effects in functions), but has
the odd attitude that side effects
are only OK if they are not announced in the spec. 

Consider the following:

   function f return integer;
   --  Increments the global variable Q and returns the
   --  incremented value.

   function f (Q : in out integer) return integer;
   --  Increments its argument and returns the incremented
   --  value.

I find it odd that Ada allows the first and disallows the
second, and many others would agree with me. Nick, no one
will try to convince you that you are wrong here, because
it is a waste of time, but you should learn that you are
quite wrong if you think your viewpoint somehow represents
a general consensus. I and many other experts in programming languages
in general, and Ada in particular,
disagree with you. The fact is there is no consensus on
either side of this issue.

Oddly, the feeling that goto statements should never be
used has much *stronger* support than the feeling that
IN OUT parameters should not be allowed in functions, yet
Ada does permit goto statements. I think the actual situation is that
this is one of these cases where the
designers get to decide, since there is no consensus.
JDI accepted gotos, but felt that functions should have
no side effects whatever. That was untenable, and he was
argued out of this extreme position, with the result that
we ended up with a rather odd compromise. Tuck is also
somewhat (though not fanatically like you) opposed to IN
OUT parameters for functions, so was not about to decree
that they should go in.

> That principle is taught for very good
> software engineering reasons. I said "Must I really
> repeat these?".

If you have been taught that functions should never ever
have side effects, you have been taught by a fanatic. Such
fanaticism is almost never helpful.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05  2:46                       ` Robert Dewar
@ 2001-11-05  7:26                         ` pete
  2001-11-05 10:29                           ` Dmitry A. Kazakov
  2001-11-05 13:56                           ` Robert Dewar
  2001-11-05 15:56                         ` Ted Dennison
  2001-11-05 18:46                         ` Nick Roberts
  2 siblings, 2 replies; 28+ messages in thread
From: pete @ 2001-11-05  7:26 UTC (permalink / raw)


 
functions, in the mathemtical sense, do not accept an IN OUT paramters,
and do not have side effects.

y=f(x), x here can never be modified by the function f().

so, Ada function is more like a math function.




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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05  7:26                         ` pete
@ 2001-11-05 10:29                           ` Dmitry A. Kazakov
  2001-11-05 11:19                             ` pete
  2001-11-06  0:10                             ` Nick Roberts
  2001-11-05 13:56                           ` Robert Dewar
  1 sibling, 2 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2001-11-05 10:29 UTC (permalink / raw)


On 4 Nov 2001 23:26:03 -0800, pete@nospam <pete_member@newsguy.com>
wrote:

>functions, in the mathemtical sense, do not accept an IN OUT paramters,
>and do not have side effects.
>
>y=f(x), x here can never be modified by the function f().
>
>so, Ada function is more like a math function.

No function in a programming language may have no side effects. One
could say that there are side effects which are of no interest, but no
more than that.

The discussion about in out parameters is proved to be evergreen
(:-)). But what I presonally cannot understand is why not to allow
PROCEDUREs having a result, i.e.

procedure Find (Folder : in out Table) return Table_Token;

procedure GetNext  (Item_List : in out Iterator) return Element;

etc.

Regards,
Dmitry Kazakov



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 10:29                           ` Dmitry A. Kazakov
@ 2001-11-05 11:19                             ` pete
  2001-11-05 14:59                               ` Dmitry A. Kazakov
  2001-11-06  0:10                             ` Nick Roberts
  1 sibling, 1 reply; 28+ messages in thread
From: pete @ 2001-11-05 11:19 UTC (permalink / raw)


In article <3be666fe.6426140@News.CIS.DFN.DE>, dmitry@elros.cbb-automation.de
says...
>
 
>But what I presonally cannot understand is why not to allow
>PROCEDUREs having a result, i.e.
>
>procedure Find (Folder : in out Table) return Table_Token;
>
>procedure GetNext  (Item_List : in out Iterator) return Element;
>
 
this is a joke, right?




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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05  7:26                         ` pete
  2001-11-05 10:29                           ` Dmitry A. Kazakov
@ 2001-11-05 13:56                           ` Robert Dewar
  2001-11-05 16:08                             ` Ted Dennison
  1 sibling, 1 reply; 28+ messages in thread
From: Robert Dewar @ 2001-11-05 13:56 UTC (permalink / raw)


pete@nospam <pete_member@newsguy.com> wrote in message news:<9s5eub02j61@drn.newsguy.com>...
> functions, in the mathemtical sense, do not accept an IN OUT paramters,
> and do not have side effects.
> 
> y=f(x), x here can never be modified by the function f().
> 
> so, Ada function is more like a math function.

Yes of course, that is the naive view that might be taught
in a beginning course, but it is bogus. Sure, Ada functions
can be used to model mathematical functions, that's true
in any case, but Ada functions are not a bit like math
functions. Mathematical functions cannot take pointer
arguments allowing modification of the calling variable,
mathematical functions cannot generate output on files,
mathematical functions cannot modify global variables.

Mathematical functions are very restrictive, and the language makes no
attempt to limit the semantics to
functions that have some sensible meaning as mathematical
functions.

That's the whole point here. Functions in Ada DO allow
side effects quite freely, and what seems odd is the
Ada rule in this case:

Functions are allowed to have side effects, providing that
there is no trace of this in the function specification :-)

The real issue here, and the point at which this becomes
significant, is that we use functions in Ada for interfacing to
foreign languages and there the restriction
is quite onerous, as anyone who has designed bindings to
C knows. Yes, access parameters help, but the requirement
that access parameters be non-null means that this usage
often is inapplicable.

For an example of functions that modify their parameters,
which is in fact possible in GNAT in some cases, using
implementation dependent features, see gnat.spitbol.patterns
(g-spipat.ads). Here the goal was
to model SNOBOL-4 style as closely as possible, and in
some cases, functions modifying their parameters lead to
the most natural usage from a SNOBOL-4 point of view. 
Since the point of this package is to assist in translation
of existing SNOBOL-4 programs, stylistic considerations
are significant. 

If (important criterion) you are familiar with SNOBOL4,
feel free to suggest other approaches that would avoid
this usage, I didn't find anything as convenient, and
would have preferred being able to program this in a more
direct manner.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 11:19                             ` pete
@ 2001-11-05 14:59                               ` Dmitry A. Kazakov
  2001-11-05 15:21                                 ` Preben Randhol
  0 siblings, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2001-11-05 14:59 UTC (permalink / raw)


On 5 Nov 2001 03:19:39 -0800, pete@nospam <pete_member@newsguy.com>
wrote:

>In article <3be666fe.6426140@News.CIS.DFN.DE>, dmitry@elros.cbb-automation.de
>says...
>>
> 
>>But what I presonally cannot understand is why not to allow
>>PROCEDUREs having a result, i.e.
>>
>>procedure Find (Folder : in out Table) return Table_Token;
>>
>>procedure GetNext  (Item_List : in out Iterator) return Element;
>>
> 
>this is a joke, right?

Nope. It is exactly what is required, namely a subroutine having a
distinguished parameter called result and allowed to modify its
arguments. It is not a function (in Ada sense), thus it is a
procedure. Compare:

procedure Find (Folder : in out Table) return Table_Token;

with

procedure Find (Folder : in out Table; Result : out Table_Token);

The difference between them is rather syntactical. Semantically they
do same: search table, cash internally the result of search (thus in
out for the fist argument), return the found element.

Regards,
Dmitry Kazakov



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 14:59                               ` Dmitry A. Kazakov
@ 2001-11-05 15:21                                 ` Preben Randhol
  2001-11-05 16:04                                   ` Ted Dennison
  2001-11-05 16:33                                   ` Dmitry A. Kazakov
  0 siblings, 2 replies; 28+ messages in thread
From: Preben Randhol @ 2001-11-05 15:21 UTC (permalink / raw)


On Mon, 05 Nov 2001 14:59:15 GMT, Dmitry A. Kazakov wrote:
> On 5 Nov 2001 03:19:39 -0800, pete@nospam <pete_member@newsguy.com>
> wrote:
> 
> procedure Find (Folder : in out Table) return Table_Token;
> 
> with
> 
> procedure Find (Folder : in out Table; Result : out Table_Token);
> 
> The difference between them is rather syntactical. Semantically they

Yes and I don't understand why you want it. What if you expect to change
two wariables in the procedure like:

procedure Find (Folder : in out Table; Result : out Table_Token; 
                Unique : out Boolean);

to do it like: 

procedure Find (Folder : in out Table; Unique : out Boolean) return Table_Token;

looks a bit messy I think.

What is the difference between a function with in out and a procedure
with a return value? It amounts to the same thing I think.

Preben



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05  2:46                       ` Robert Dewar
  2001-11-05  7:26                         ` pete
@ 2001-11-05 15:56                         ` Ted Dennison
  2001-11-05 18:46                         ` Nick Roberts
  2 siblings, 0 replies; 28+ messages in thread
From: Ted Dennison @ 2001-11-05 15:56 UTC (permalink / raw)


In article <5ee5b646.0111041846.93f3e07@posting.google.com>, Robert Dewar
says...
>No, this is by no means a consensus. Most procedural
>languages, including Ada, allow functions to have side
>effects. And on the narrower issue of allowing IN OUT

C actually does not allow "OUT" parameters in functions either. In fact its even
worse than Ada here, in that it doesn't have procedures either, so there is *no*
language-defined way to pass values out through a paramter. I does allow one to
get around this restriction using pointers, but then so does Ada.

>Most people feel that being forced to add aliased keywords
>all over the place, just because of odd interfacing requirements for C
>functions, is unfortunate. If you find

Any C interfacing code is going to be somewhat ugly, not due to any failing in
Ada, just because C *is* ugly. That's why "most people" I talk to prefer thick C
bindings, to localize the uglyness.

Now all this being said, I am beginning to come around to your point of view.
Perhaps value-returning procedures should be reconsidered for the next Ada rev?
That would let folks keep their no (visible) side-effect functions.

I'm also beginning to think that some rethinking needs to be done about Ada's
whole parameter-passing scheme. It works well for public types, but blows for
private types. For a private type, its quite possible for me to not want to
change the users' view of a parameter, but to want to change some internal data
in it (eg: cache a location in a structure to speed up the next access if it is
liable to be nearby). Labelling such parameters as "in out" misleads the clients
(and not so incidentally, prevents use of functions). I'm getting really tired
of the gymnastics the language makes me go through to do this. Rosen trick
aside, there ought to be a way to specify certian portions of a private record
and tagged types as "internal", and thus always updatatable.

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html

No trees were killed in the sending of this message. 
However a large number of electrons were terribly inconvenienced.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 15:21                                 ` Preben Randhol
@ 2001-11-05 16:04                                   ` Ted Dennison
  2001-11-05 16:33                                   ` Dmitry A. Kazakov
  1 sibling, 0 replies; 28+ messages in thread
From: Ted Dennison @ 2001-11-05 16:04 UTC (permalink / raw)


In article <slrn9udfg3.4dc.randhol+abuse@kiuk0156.chembio.ntnu.no>, Preben
Randhol says...
>
>What is the difference between a function with in out and a procedure
>with a return value? It amounts to the same thing I think.

I think it would actually give functions *back* their purity. It would allow
functions to continue to be used for non-side-effect functions, but give folks
who would otherwise have to resort to pointers, unchecked_access tricks, or the
Rosen trick in a function a language-defined way to achieve the result they
require. When reading a spec, "function" would be a bit stronger of a statement
about what is going on. Plus folks who feel religously about it could just
outlaw value-returning procedures like they always have for "goto".

However, I think about %90 of this issue would go away if some other method of
modifying "bookkeeping" fields in private types was provided.

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html

No trees were killed in the sending of this message. 
However a large number of electrons were terribly inconvenienced.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 13:56                           ` Robert Dewar
@ 2001-11-05 16:08                             ` Ted Dennison
  2001-11-05 17:44                               ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 28+ messages in thread
From: Ted Dennison @ 2001-11-05 16:08 UTC (permalink / raw)


In article <5ee5b646.0111050556.1f9137ff@posting.google.com>, Robert Dewar
says...
>
>The real issue here, and the point at which this becomes
>significant, is that we use functions in Ada for interfacing to
>foreign languages and there the restriction
>is quite onerous, as anyone who has designed bindings to
>C knows. Yes, access parameters help, but the requirement
>that access parameters be non-null means that this usage
>often is inapplicable.

Actually access parameters are next to useless in C bindings for that very
reason.

However this isn't a huge issue with C bindings, as C has no "out" parameters in
functions either. At *worst*, you have to do what C coders have to do: use
pointers. If you lie down with dogs, you are going to get up with fleas. :-)

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html

No trees were killed in the sending of this message. 
However a large number of electrons were terribly inconvenienced.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 15:21                                 ` Preben Randhol
  2001-11-05 16:04                                   ` Ted Dennison
@ 2001-11-05 16:33                                   ` Dmitry A. Kazakov
  2001-11-05 17:42                                     ` Warren W. Gay VE3WWG
  1 sibling, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2001-11-05 16:33 UTC (permalink / raw)


On Mon, 5 Nov 2001 15:21:13 +0000 (UTC), Preben Randhol
<randhol+abuse@pvv.org> wrote:

>On Mon, 05 Nov 2001 14:59:15 GMT, Dmitry A. Kazakov wrote:
>> On 5 Nov 2001 03:19:39 -0800, pete@nospam <pete_member@newsguy.com>
>> wrote:
>> 
>> procedure Find (Folder : in out Table) return Table_Token;
>> 
>> with
>> 
>> procedure Find (Folder : in out Table; Result : out Table_Token);
>> 
>> The difference between them is rather syntactical. Semantically they
>
>Yes and I don't understand why you want it. What if you expect to change
>two wariables in the procedure like:
>
>procedure Find (Folder : in out Table; Result : out Table_Token; 
>                Unique : out Boolean);

Well, multiple results is another story. Some languages have return
tuples, but I am not convinced that Ada really needs it.

Then your argument could be well applied to pure functions as well.
Why not to replace them by procedures with an extra out parameter? A
bit more work with temporal variables, unability to initialize
constants, but generally no problem (:-))

>to do it like: 
>
>procedure Find (Folder : in out Table; Unique : out Boolean) return Table_Token;
>
>looks a bit messy I think.

Yes. But I still have a choice to make it:

procedure Find (Folder : in out Table; Result : out Table_Token; 
                Unique : out Boolean);

It is of course not so that any out parameter has to be declared as
the result. All we need is an impure function. As Robert have pointed,
it is ridiculous to have an ability to write impure functions and have
no right to manifest them as such (openly using in out parameters). If
the word "function" makes people so sensitive, let's use "procedure"
instead!

>What is the difference between a function with in out and a procedure
>with a return value? It amounts to the same thing I think.

There is no difference other than functions with in out parameters are
unacceptable for some part of Ada community, which is enough powerful
to ban them forever (:-)).

P.S. I do not belong to this part.

Regards,
Dmitry Kazakov



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 16:33                                   ` Dmitry A. Kazakov
@ 2001-11-05 17:42                                     ` Warren W. Gay VE3WWG
  2001-11-05 18:11                                       ` Preben Randhol
  2001-11-06  8:38                                       ` Dmitry A. Kazakov
  0 siblings, 2 replies; 28+ messages in thread
From: Warren W. Gay VE3WWG @ 2001-11-05 17:42 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> On Mon, 5 Nov 2001 15:21:13 +0000 (UTC), Preben Randhol
> <randhol+abuse@pvv.org> wrote:
>>On Mon, 05 Nov 2001 14:59:15 GMT, Dmitry A. Kazakov wrote:
>>>On 5 Nov 2001 03:19:39 -0800, pete@nospam <pete_member@newsguy.com>
>>>wrote:
...
> Yes. But I still have a choice to make it:
> 
> procedure Find (Folder : in out Table; Result : out Table_Token; 
>                 Unique : out Boolean);
> 
> It is of course not so that any out parameter has to be declared as
> the result. All we need is an impure function. As Robert have pointed,
> it is ridiculous to have an ability to write impure functions and have
> no right to manifest them as such (openly using in out parameters). If
> the word "function" makes people so sensitive, let's use "procedure"
> instead!
> 
>>What is the difference between a function with in out and a procedure
>>with a return value? It amounts to the same thing I think.
> 
> There is no difference other than functions with in out parameters are
> unacceptable for some part of Ada community, which is enough powerful
> to ban them forever (:-)).
> 
> P.S. I do not belong to this part.
> 
> Regards,
> Dmitry Kazakov


I think one of the issues at stake here is that Ada was meant to be

easy to read. If you allow procedures to return values, then it is
no longer a valid assumption that what looks like a function call,
does not produce side effects (ie. you cannot assume that the arguments
are not modified, without looking at the declaration).


To pull it off, you'd have to make some sort of syntactical difference

in procedure-function calls, to maintain the status quo for functions.
In case I am not explaining this clear enough, the following example
might help:

declare
    Arg : Boolean;		-- Argument
    R   : Boolean;		-- Result
begin

    R := My_Function(Arg);	-- Assumed that Arg is not modified
    R := My_Proc_Function[Arg];	-- A procedure returning.. identified by []


I am not suggesting the [] make a good syntax here, but you'd have
to do something like this to maintain the distinction that Functions
already enjoy within Ada.
-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 16:08                             ` Ted Dennison
@ 2001-11-05 17:44                               ` Warren W. Gay VE3WWG
  0 siblings, 0 replies; 28+ messages in thread
From: Warren W. Gay VE3WWG @ 2001-11-05 17:44 UTC (permalink / raw)


Ted Dennison wrote:

> In article <5ee5b646.0111050556.1f9137ff@posting.google.com>, Robert Dewar
> says...
...

> However this isn't a huge issue with C bindings, as C has no "out" parameters in
> functions either. At *worst*, you have to do what C coders have to do: use
> pointers. If you lie down with dogs, you are going to get up with fleas. :-)


You may also "smell like dogs" ;-)


-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 17:42                                     ` Warren W. Gay VE3WWG
@ 2001-11-05 18:11                                       ` Preben Randhol
  2001-11-06  8:38                                       ` Dmitry A. Kazakov
  1 sibling, 0 replies; 28+ messages in thread
From: Preben Randhol @ 2001-11-05 18:11 UTC (permalink / raw)


On Mon, 05 Nov 2001 17:42:14 GMT, Warren W. Gay VE3WWG wrote:
> 
> I think one of the issues at stake here is that Ada was meant to be
> 
> easy to read. If you allow procedures to return values, then it is
> no longer a valid assumption that what looks like a function call,
> does not produce side effects (ie. you cannot assume that the arguments
> are not modified, without looking at the declaration).

Not only that. If one allow return values in procedures one cannot know
that the procedure won't return a value unless one look at the
definition. It would make things a mess and I think it clearly would
break down readability. 

>     R := My_Function(Arg);	-- Assumed that Arg is not modified
>     R := My_Proc_Function[Arg];	-- A procedure returning.. identified by []
> 
> 
> I am not suggesting the [] make a good syntax here, but you'd have
> to do something like this to maintain the distinction that Functions
> already enjoy within Ada.

Ouch! Very bad (I think) as you then will introduce:

1. Very confusing syntax for beginners
2. Harder to "read" the difference => Lower readability
3. More easy to write wrong code. You may type [] and mean (). 
4. How should one solve dispatching?

I don't understand the need for neither function with in out nor
procedure with return values.

Preben Randhol
-- 
Please, stop bombing civilians in Afghanistan. One cannot write off
killing innocent children and other civilians as "collateral damage".
A civilian is a civilian whether he or she is American or from another
country in the world.           http://web.amnesty.org/11september.htm



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05  2:46                       ` Robert Dewar
  2001-11-05  7:26                         ` pete
  2001-11-05 15:56                         ` Ted Dennison
@ 2001-11-05 18:46                         ` Nick Roberts
  2001-11-08 11:51                           ` Georg Bauhaus
  2 siblings, 1 reply; 28+ messages in thread
From: Nick Roberts @ 2001-11-05 18:46 UTC (permalink / raw)


Just briefly, because I don't want to waste any more of my time on this, I'm
not entirely sure whether Robert is being serious, or is just arguing for
the fun of it (or something).

As to the issue of whether Ada should permit in-out parameters in functions,
I hold no strong opinion, and my original point had nothing to do with this.
Maybe it would be a nice idea, but you can always use a procedure instead;
no big deal. The 'problems' cited by various people about using access
parameters for interfacing with C functions are silly: if you need to be
able to pass a null value, you use an access type (and pass it in as an 'in'
parameter); again, no big deal.

On whether it is good practice to program functions with side-effects, in a
procedural language which doesn't specify the order in which the arguments
of functions are evaluated (such as Ada), I hold the very strong opinion
that it is generally not, for the perfectly rational, and well-established,
reason that it can introduce subtle and pernicious bugs. Robert has said
absolutely nothing to refute this. Twisting the argument between what can
and should be done may be a clever rhetorical technique, but it isn't good
science.

--
Nick Roberts






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

* Re: Side-Effects in Functions [Rosen Trick]
@ 2001-11-05 21:10 Alexandre E. Kopilovitch
  2001-11-05 21:58 ` Brian Rogoff
  0 siblings, 1 reply; 28+ messages in thread
From: Alexandre E. Kopilovitch @ 2001-11-05 21:10 UTC (permalink / raw)
  To: comp.lang.ada

dewar@gnat.com (Robert Dewar) wrote:
>That's the whole point here. Functions in Ada DO allow
>side effects quite freely, and what seems odd is the
>Ada rule in this case:
>
>Functions are allowed to have side effects, providing that
>there is no trace of this in the function specification :-)

Well, but if we allow the side effects within the function specification,
what will be the essential difference between the functions and the procedures?
Why should we have both notions instead of one? We may easily follow the C view,
on this subject, and have the functions only, permitting 'null' for the return
type.

Indeed, Ada frequently uses the common term 'subprogram' for both functions
and procedures, but only in the textual part of the language definition. It
means that we are permitted to think and speak about 'subprograms', but must
differentiate them in our code as either 'functions' or 'procedures'. What is
the purpose of that differentiation?

>The real issue here, and the point at which this becomes
>significant, is that we use functions in Ada for interfacing to
>foreign languages and there the restriction
>is quite onerous, as anyone who has designed bindings to
>C knows. Yes, access parameters help, but the requirement
>that access parameters be non-null means that this usage
>often is inapplicable.

I think that if we are going to retain "function" and "procedure" as separate
entities in the language, then introducing vector results is more consistent
way than permitting OUT parameters.



Alexander Kopilovitch                      aek@vib.usr.pu.ru
Saint-Petersburg
Russia





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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 21:10 Side-Effects in Functions [Rosen Trick] Alexandre E. Kopilovitch
@ 2001-11-05 21:58 ` Brian Rogoff
  2001-11-22  6:22   ` David Thompson
  0 siblings, 1 reply; 28+ messages in thread
From: Brian Rogoff @ 2001-11-05 21:58 UTC (permalink / raw)


On Tue, 6 Nov 2001, Alexandre E. Kopilovitch wrote:
> dewar@gnat.com (Robert Dewar) wrote:
> >That's the whole point here. Functions in Ada DO allow
> >side effects quite freely, and what seems odd is the
> >Ada rule in this case:
> >
> >Functions are allowed to have side effects, providing that
> >there is no trace of this in the function specification :-)
>
> Well, but if we allow the side effects within the function specification,
> what will be the essential difference between the functions and the
> procedures?

Functions return values. There is no "void" or "unit" (ML) type in Ada.

> Why should we have both notions instead of one?

Hysterical raisins. What happened with Wirth's post-Pascal languages?

FWIW, I agreed with everything Robert Dewar wrote in his excellent post,
and *if Ada could be redesigned from scratch* I personally would prefer
no distinction between functions and procedures, but rather a void or unit
type. However, it is more likely that monkeys will suddenly fly out my
butt than it is that we'll have an incompatible new version of Ada.

> We may easily follow the C view, on this subject, and have the
> functions only, permitting 'null' for the return type.

It's called void, not null. The problem with C is that it ignores returned
value types so even though it has void it doesn't really use it. I imagine
a reworked Ada would only allow void returning function/procedure values
to be ignores, and so wouldn't lose type safety.

> >The real issue here, and the point at which this becomes
> >significant, is that we use functions in Ada for interfacing to
> >foreign languages and there the restriction
> >is quite onerous, as anyone who has designed bindings to
> >C knows. Yes, access parameters help, but the requirement
> >that access parameters be non-null means that this usage
> >often is inapplicable.
>
> I think that if we are going to retain "function" and "procedure" as separate
> entities in the language, then introducing vector results is more consistent
> way than permitting OUT parameters.

I disagree. I think allowing "in out", NOT OUT, parameters for functions
would be the best upwardly compatible fix. As Dr. Dewar wrote, it is
unlikely to happen, so Ada fans just have to tolerate this annoyance or
go elsewhere.

-- Brian





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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 10:29                           ` Dmitry A. Kazakov
  2001-11-05 11:19                             ` pete
@ 2001-11-06  0:10                             ` Nick Roberts
  2001-11-06  9:30                               ` Dmitry A. Kazakov
  2001-11-06 20:08                               ` Florian Weimer
  1 sibling, 2 replies; 28+ messages in thread
From: Nick Roberts @ 2001-11-06  0:10 UTC (permalink / raw)


"Dmitry A. Kazakov" <dmitry@elros.cbb-automation.de> wrote in message
news:3be666fe.6426140@News.CIS.DFN.DE...
> On 4 Nov 2001 23:26:03 -0800, pete@nospam <pete_member@newsguy.com>
> wrote:
>
> >functions, in the mathemtical sense, do not accept an IN OUT paramters,
> >and do not have side effects.
> >
> >y=f(x), x here can never be modified by the function f().
> >
> >so, Ada function is more like a math function.

From a pedagogical point of view, care needs to be taken not to give the
impression that a function in a procedural programming language (most
programming languages, really) is the same thing as a mathematical function.
Clearly it isn't: a mathematical function is a kind of relation called a
'bijection' (and is nowadays specifically defined as such, I think); a
programming function is really just an encapsulated computation.

Nevertheless, because a great many (practically useful) computations are, in
fact, essentially to work out the mapping represented by a mathematical
function from one value to another, it has become idiomatic to call these
computations functions. Classic examples include such functions as sin, cos,
and tan. Since the computations involve no side-effects, they neatly fit the
'no side-effects' model for programming functions.

> No function in a programming language may have no side effects. One
> could say that there are side effects which are of no interest, but no
> more than that.

I think, perhaps, that depends on precisely how you define a side-effect. If
you include modification of registers or memory as side-effects, then it's
true. However, we are only interested in side-effects in which we are
interested!

> The discussion about in out parameters is proved to be evergreen
> (:-)). But what I presonally cannot understand is why not to allow
> PROCEDUREs having a result, i.e.
>
> procedure Find (Folder : in out Table) return Table_Token;
>
> procedure GetNext  (Item_List : in out Iterator) return Element;

It would be pointless to have value-returning procedures in Ada. The reason
why is because procedures of this kind would suffer from precisely the same
dangers as functions (and would therefore be of no benefit over functions).

I'm going to spell out the problems with side-effects in functions, so that
(hopefully) everyone will be aware of them.

Ada (like many procedural languages) permits compilers to evaluate the
arguments of a function call in any order it chooses. (Obviously we are
talking about a functions with more than one parameter here.) The arguments
to this function call could be other function calls (nested within). For
example:

   A := B(C(E),D(E));

B, C, and D are all functions. First, the compiler will compile code to
evaluate E, then it will compile code to evaluate (call) C and D, and then
finally code that evaluates (calls) B, passing in the results from C and D.
The code calling C may come before or after the code calling D: it is the
choice of the compiler.

Now, suppose B, C, and D all have a side-effect when called: they print
their name onto a log file. The result on the log file of compiling and
executing this line of code with one compiler could be "C D B", but with
another compiler it could be "D C B". You have the self-same program,
compiled on two perfectly correct and compliant compilers, doing two
different things.

The two different behaviours may seem innocuous in the above example, but
consider this example, adapted from a real-life situation:

   Header := Decode(Data(1..4)) & Decode(Data(5..8));

The Decode function was really a pseudo-random number generator, but it used
the values it generated to decode an encrypted message. It used a global
variable for its state, which had to be seeded with the correct encryption
key; its side-effect was to update this state. Each 'chunk' that it decoded
had to be 4 bytes long.

The header of a certain message format was 8 bytes long, so we passed it
into Decode in two 4-byte chunks, as shown. This code worked fine for us,
but half-way through the project we changed compilers, and suddenly it
stopped working. Nobody had altered the code. Recriminations flew. Can you
see what had happened?

Answer: the first compiler evaluated Decode(Data(1..4)) first, and
Decode(Data(5..8)) second. So the first decryption value generated (at that
point in the program) by Decode was used on Data(1..4) first, and the second
on Data(5..8); the second compiler did it the other way around (as it was
perfectly entitled to do, since the two calls to Decode are the two
arguments of a call to "&").

If we had declared Decode as a procedure instead, and then written:

   Decode(Data(1..4),Header(1..4));
   Decode(Data(5..8),Header(5..8));

this bizarre and mystifying problem would never had occurred (and a certain
blameless manager -- not myself, I was a junior at the time -- would
probably not had been sacked).

Side-effects can be programmed into functions quite safely, if you know what
you're doing. As a rule of thumb, either: (a) diligently ensure that the
side-effect can't possibly cause a (significant) problem due to an
'order-of-evaluation dependency', or (b) remove the side-effect.

Typically, the easiest way to remove a side-effect from a function is to
turn the function into a procedure.

I hope I've convinced any doubters, at this point. If you're still not sure,
just trust your uncle Nicky, eh?

--
Nick Roberts






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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 17:42                                     ` Warren W. Gay VE3WWG
  2001-11-05 18:11                                       ` Preben Randhol
@ 2001-11-06  8:38                                       ` Dmitry A. Kazakov
  2001-11-06  9:31                                         ` tgingold
  1 sibling, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2001-11-06  8:38 UTC (permalink / raw)


On Mon, 05 Nov 2001 17:42:14 GMT, "Warren W. Gay VE3WWG"
<ve3wwg@home.com> wrote:

>I think one of the issues at stake here is that Ada was meant to be
>
>easy to read. If you allow procedures to return values, then it is
>no longer a valid assumption that what looks like a function call,
>does not produce side effects (ie. you cannot assume that the arguments
>are not modified, without looking at the declaration).

Why something that looks like a call returning a result should have no
side effects? There are two completely different and independent
properties of a subroutine:

a) It does not modify arguments
b) It returns a result

What we have in Ada is:

subroutine is a function => a & b
subroutine is a procedure => not b

Now the question, why on Earth b=>a?

>To pull it off, you'd have to make some sort of syntactical difference
>
>in procedure-function calls, to maintain the status quo for functions.
>In case I am not explaining this clear enough, the following example
>might help:
>
>declare
>    Arg : Boolean;		-- Argument
>    R   : Boolean;		-- Result
>begin
>
>    R := My_Function(Arg);	-- Assumed that Arg is not modified
>    R := My_Proc_Function[Arg];	-- A procedure returning.. identified by []
>
>I am not suggesting the [] make a good syntax here, but you'd have
>to do something like this to maintain the distinction that Functions
>already enjoy within Ada.

Seems like Hungarian notation reincarnation. It is IMO a wrong idea.
All that a user should know about a subroutine is its contract. The
parameter mode is a part of the contract. When a user do not want (in
your example) Arg to be modified, he/she must simply say it by
declaring Arg constant, which would make the second call illegal.

Regards,
Dmitry Kazakov



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-06  0:10                             ` Nick Roberts
@ 2001-11-06  9:30                               ` Dmitry A. Kazakov
  2001-11-06 20:08                               ` Florian Weimer
  1 sibling, 0 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2001-11-06  9:30 UTC (permalink / raw)


On Tue, 6 Nov 2001 00:10:31 -0000, "Nick Roberts"
<nickroberts@adaos.worldonline.co.uk> wrote:

>"Dmitry A. Kazakov" <dmitry@elros.cbb-automation.de> wrote in message
>news:3be666fe.6426140@News.CIS.DFN.DE...
>> On 4 Nov 2001 23:26:03 -0800, pete@nospam <pete_member@newsguy.com>
>> wrote:
>>
>> >functions, in the mathemtical sense, do not accept an IN OUT paramters,
>> >and do not have side effects.
>> >
>> >y=f(x), x here can never be modified by the function f().
>> >
>> >so, Ada function is more like a math function.
>
>From a pedagogical point of view, care needs to be taken not to give the
>impression that a function in a procedural programming language (most
>programming languages, really) is the same thing as a mathematical function.
>Clearly it isn't: a mathematical function is a kind of relation called a
>'bijection' (and is nowadays specifically defined as such, I think); a
>programming function is really just an encapsulated computation.
>
>Nevertheless, because a great many (practically useful) computations are, in
>fact, essentially to work out the mapping represented by a mathematical
>function from one value to another, it has become idiomatic to call these
>computations functions. Classic examples include such functions as sin, cos,
>and tan. Since the computations involve no side-effects, they neatly fit the
>'no side-effects' model for programming functions.
>
>> No function in a programming language may have no side effects. One
>> could say that there are side effects which are of no interest, but no
>> more than that.
>
>I think, perhaps, that depends on precisely how you define a side-effect. If
>you include modification of registers or memory as side-effects, then it's
>true. However, we are only interested in side-effects in which we are
>interested!

It is a great problem to give a careful definition of side-effects.
Ada follows rather a pragmatic view, side-effects are ones of
arguments. Unfortunately this definition is too weak for correctness
checks. Though I doubt that a correct definition exists. Just consider
an assertion that includes absolute time!

>> The discussion about in out parameters is proved to be evergreen
>> (:-)). But what I presonally cannot understand is why not to allow
>> PROCEDUREs having a result, i.e.
>>
>> procedure Find (Folder : in out Table) return Table_Token;
>>
>> procedure GetNext  (Item_List : in out Iterator) return Element;
>
>It would be pointless to have value-returning procedures in Ada. The reason
>why is because procedures of this kind would suffer from precisely the same
>dangers as functions (and would therefore be of no benefit over functions).
>
>I'm going to spell out the problems with side-effects in functions, so that
>(hopefully) everyone will be aware of them.
>
>Ada (like many procedural languages) permits compilers to evaluate the
>arguments of a function call in any order it chooses. (Obviously we are
>talking about a functions with more than one parameter here.) The arguments
>to this function call could be other function calls (nested within). For
>example:
>
>   A := B(C(E),D(E));
>
>B, C, and D are all functions. First, the compiler will compile code to
>evaluate E, then it will compile code to evaluate (call) C and D, and then
>finally code that evaluates (calls) B, passing in the results from C and D.
>The code calling C may come before or after the code calling D: it is the
>choice of the compiler.
>
>Now, suppose B, C, and D all have a side-effect when called: they print
>their name onto a log file. The result on the log file of compiling and
>executing this line of code with one compiler could be "C D B", but with
>another compiler it could be "D C B". You have the self-same program,
>compiled on two perfectly correct and compliant compilers, doing two
>different things.
>
>The two different behaviours may seem innocuous in the above example, but
>consider this example, adapted from a real-life situation:
>
>   Header := Decode(Data(1..4)) & Decode(Data(5..8));
>
>The Decode function was really a pseudo-random number generator, but it used
>the values it generated to decode an encrypted message. It used a global
>variable for its state, which had to be seeded with the correct encryption
>key; its side-effect was to update this state. Each 'chunk' that it decoded
>had to be 4 bytes long.
>
>The header of a certain message format was 8 bytes long, so we passed it
>into Decode in two 4-byte chunks, as shown. This code worked fine for us,
>but half-way through the project we changed compilers, and suddenly it
>stopped working. Nobody had altered the code. Recriminations flew. Can you
>see what had happened?
>
>Answer: the first compiler evaluated Decode(Data(1..4)) first, and
>Decode(Data(5..8)) second. So the first decryption value generated (at that
>point in the program) by Decode was used on Data(1..4) first, and the second
>on Data(5..8); the second compiler did it the other way around (as it was
>perfectly entitled to do, since the two calls to Decode are the two
>arguments of a call to "&").
>
>If we had declared Decode as a procedure instead, and then written:
>
>   Decode(Data(1..4),Header(1..4));
>   Decode(Data(5..8),Header(5..8));
>
>this bizarre and mystifying problem would never had occurred (and a certain
>blameless manager -- not myself, I was a junior at the time -- would
>probably not had been sacked).
>
>Side-effects can be programmed into functions quite safely, if you know what
>you're doing. As a rule of thumb, either: (a) diligently ensure that the
>side-effect can't possibly cause a (significant) problem due to an
>'order-of-evaluation dependency', or (b) remove the side-effect.
>
>Typically, the easiest way to remove a side-effect from a function is to
>turn the function into a procedure.
>
>I hope I've convinced any doubters, at this point. If you're still not sure,
>just trust your uncle Nicky, eh?

The above is of course correct. Perhaps everybody enjoyed things like
that at least once [lucky ones did it several times (:-))] 

Yet it proves nothing more than if you have side-effects then, well,
there are side-effects.

Side-effects are bad, dangerous, nasty,... but sometimes necessary.
Then, can Ada's functions prevent users from writting things like
above? The answer is no.

P.S. A comment about computation order. I am not sure, but maybe it
would be worth to think about introducing lazy parameters (Algol's by
name). Ada already has them hard-wired in "and then" and "or else".
The order lazy parameters are evaluated is obviously defined by the
implementation of the subroutine, thus the above problems will
disappear, or better to say, become the responsibility of the
implementation. In your example "&" should have the second parameter
lazy, so 

    Decode(Data(1..4)) & Decode(Data(5..8));

would  mean: evaluate Decode(Data(1..4)); call "&", which internally
calls Decode(Data(5..8)).

Regards,
Dmitry Kazakov



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-06  8:38                                       ` Dmitry A. Kazakov
@ 2001-11-06  9:31                                         ` tgingold
  0 siblings, 0 replies; 28+ messages in thread
From: tgingold @ 2001-11-06  9:31 UTC (permalink / raw)


In article <3be79e7c.551796@News.CIS.DFN.DE>, Dmitry A. Kazakov wrote:
> On Mon, 05 Nov 2001 17:42:14 GMT, "Warren W. Gay VE3WWG"
><ve3wwg@home.com> wrote:
> 
>>I think one of the issues at stake here is that Ada was meant to be
>>
>>easy to read. If you allow procedures to return values, then it is
>>no longer a valid assumption that what looks like a function call,
>>does not produce side effects (ie. you cannot assume that the arguments
>>are not modified, without looking at the declaration).
Just for your information, VHDL-93 has PURE and IMPURE keyword.  Such a
declaration:
  pure function sum (a,b : integer) return integer;
means that SUM has no side effects (and therefore is expected to return
the same result when the set of argument is the same).
However, INOUT and OUT mode are not allowed in IMPURE FUNCTION.

Note also that return a value is *VERY* different from an OUT parameter, since
the return type can be unconstrained.

Tristan.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-06  0:10                             ` Nick Roberts
  2001-11-06  9:30                               ` Dmitry A. Kazakov
@ 2001-11-06 20:08                               ` Florian Weimer
  2001-11-06 22:48                                 ` Nick Roberts
  1 sibling, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2001-11-06 20:08 UTC (permalink / raw)


"Nick Roberts" <nickroberts@adaos.worldonline.co.uk> writes:

> From a pedagogical point of view, care needs to be taken not to give the
> impression that a function in a procedural programming language (most
> programming languages, really) is the same thing as a mathematical function.
> Clearly it isn't: a mathematical function is a kind of relation called a
> 'bijection' (and is nowadays specifically defined as such, I think);

A function f : M -> N are two sets M, N and a subset G_f of the
Cartesian product M x N with the following property: for all m in M,
there exists exactly one n in N such that (m, n) in G_f.

> a programming function is really just an encapsulated computation.

Yes, such functions take an additional implicit argument (the machine
state before execution) and have an invisible result (the machine
state after execution).

However, there are programming languages which use only mathematical
functions, and a special construct for I/O, Haskell for example.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-06 20:08                               ` Florian Weimer
@ 2001-11-06 22:48                                 ` Nick Roberts
  2001-11-07 10:46                                   ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Nick Roberts @ 2001-11-06 22:48 UTC (permalink / raw)


"Florian Weimer" <fw@deneb.enyo.de> wrote in message
news:87itcn8xxx.fsf@deneb.enyo.de...
> "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> writes:
>
> > From a pedagogical point of view, care needs to be taken not to give the
> > impression that a function in a procedural programming language (most
> > programming languages, really) is the same thing as a mathematical
function.
> > Clearly it isn't: a mathematical function is a kind of relation called a
> > 'bijection' (and is nowadays specifically defined as such, I think);
>
> A function f : M -> N are two sets M, N and a subset G_f of the
> Cartesian product M x N with the following property: for all m in M,
> there exists exactly one n in N such that (m, n) in G_f.

That actually sounds like an injection to me (1 to 1), whereas I get the
impression mathematicians (discrete ones anyway ;-) tend to insist nowadays
on the definition of a function as a bijection (both 1 to 1 and 'onto', i.e.
both an injection and a surjection, so that f' is also a bijection). However
IANAM.

> > a programming function is really just an encapsulated computation.
>
> Yes, such functions take an additional implicit argument (the machine
> state before execution) and have an invisible result (the machine
> state after execution).

Neatly put. Of course, if the (programming) function might perform I/O, we
are potentially talking about 'world state' (or even 'universe state')
rather than just machine state! (And then we have the problem with enthalpy,
but that, as they say, is a different game of banana and clotted cream.)

> However, there are programming languages which use only mathematical
> functions, and a special construct for I/O, Haskell for example.

I'm not a Haskell expert, but functional languages in general do fix the
order of evaluation of their functions (or some of their functions)
precisely because of the side-effect problem. I presume lazy evaluation can
be a serious hazard, if used without care, nevertheless.

--
Nick Roberts






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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-06 22:48                                 ` Nick Roberts
@ 2001-11-07 10:46                                   ` Florian Weimer
  0 siblings, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2001-11-07 10:46 UTC (permalink / raw)


"Nick Roberts" <nickroberts@adaos.worldonline.co.uk> writes:

> "Florian Weimer" <fw@deneb.enyo.de> wrote in message
> news:87itcn8xxx.fsf@deneb.enyo.de...
>> "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> writes:
>>
>> > From a pedagogical point of view, care needs to be taken not to give the
>> > impression that a function in a procedural programming language (most
>> > programming languages, really) is the same thing as a mathematical
> function.
>> > Clearly it isn't: a mathematical function is a kind of relation called a
>> > 'bijection' (and is nowadays specifically defined as such, I think);
>>
>> A function f : M -> N are two sets M, N and a subset G_f of the
>> Cartesian product M x N with the following property: for all m in M,
>> there exists exactly one n in N such that (m, n) in G_f.
>
> That actually sounds like an injection to me (1 to 1), 

Actually, it's many to one.  The uniqueness constraint is only there
to ensure that for each value m in M, there is only one value of
the function at m (usually denoted by "f(m)" or "m f", if you write
functions from the right).

> whereas I get the impression mathematicians (discrete ones anyway
> ;-) tend to insist nowadays on the definition of a function as a
> bijection (both 1 to 1 and 'onto', i.e.  both an injection and a
> surjection, so that f' is also a bijection).

I've yet to meet a mathematician who claims that functions are always
bijective.  Quite the contrary, in almost all the set-based categories
I've seen so far, morphisms weren't generally bijective.

>> However, there are programming languages which use only mathematical
>> functions, and a special construct for I/O, Haskell for example.
>
> I'm not a Haskell expert, but functional languages in general do fix the
> order of evaluation of their functions (or some of their functions)
> precisely because of the side-effect problem.

Haskell functions do not have side effects.  Side effects are
introduced by a special construct call a "monad", which essentially
introduces explicit machine state parameters.  There's a construct
("do") which makes them implicit again, too.

> I presume lazy evaluation can be a serious hazard, if used without
> care, nevertheless.

Lazy evaluation is a nice thing, as long as functions have no side
effects.



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 18:46                         ` Nick Roberts
@ 2001-11-08 11:51                           ` Georg Bauhaus
  0 siblings, 0 replies; 28+ messages in thread
From: Georg Bauhaus @ 2001-11-08 11:51 UTC (permalink / raw)


Nick Roberts <nickroberts@adaos.worldonline.co.uk> wrote:
 
: On whether it is good practice to program functions with side-effects,

Well, that's it, then?


If your opinion is that strong, maybe you should really give
Haskell a chance. Also, I've found Paulson's remarks on the
issue (in an early chapter of his ML book) instructive.
(But then I am not someone with an abundance of languages and their
compilation techniques in his head, like others here, but I seem
to recall that this subject has been debated for decades?)

Georg



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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-05 21:58 ` Brian Rogoff
@ 2001-11-22  6:22   ` David Thompson
  2001-11-23  7:18     ` Brian Rogoff
  0 siblings, 1 reply; 28+ messages in thread
From: David Thompson @ 2001-11-22  6:22 UTC (permalink / raw)


Brian Rogoff <bpr@shell5.ba.best.com> wrote :
> On Tue, 6 Nov 2001, Alexandre E. Kopilovitch wrote:
...
> .... However, it is more likely that monkeys will suddenly fly out my
> butt than it is that we'll have an incompatible new version of Ada.
>
I realize we're talking about negligible probabilities here, but just
to be on the safe side, remind me not to stand behind you :-}

> > We may easily follow the C view, on this subject, and have the
> > functions only, permitting 'null' for the return type.
>
> It's called void, not null. The problem with C is that it ignores returned
> value types so even though it has void it doesn't really use it. I imagine
> a reworked Ada would only allow void returning function/procedure values
> to be ignores, and so wouldn't lose type safety.
>
I'm not sure what you were trying to say there.

C certainly does use the declared return type of a function.
If you try to assign the result of a function call to a variable
(or pass it to a prototyped parameter) of a type to which
it cannot be converted, it's a diagnosed error, just as for
any other expression yielding that type; also if you try to
assign or pass the "value" of a void function at all.
Also, if you write a return statement with a value of a type
that cannot be converted to the function's return type,
or any (real) value in a void function, it's diagnosed;
or in C99 (but not originally) to have a return without value
in a function with a non-void return type.

What you may be after is that the value of any non-void expression
in C, whether it is the return from a function or not, is discarded
if that expression constitutes an entire statment.  Thus
  sin(3.1415926);
  2+3;
are both legal though useless statements:  the former would be
useful if the function called were one with (desired) side effects,
the latter could never be.  This treatment is necessary
partly because in C the assignment operators (simple =
and also the "compound" assignments like *= ++ etc.)
_have a value_ namely the value assigned, so you can write
e.g. a = b = x; which is the same as { b = x; a = b; }
except for volatile variables or non-idempotent lvalues,
and without this discarding you would have to always write
(void)(a=3); and so on which is obviously Stupid(tm).

In addition you can explicitly ignore any value by casting
to void, but because of the above it is never really needed.
Except some compilers and most(?) lints give a _warning_
about implicitly discarding the value of a non-assignment,
so if you use those tools you do need to cast to void
to avoid (ha, ha) the warning.  Similarly you can often get
a warning for writing if(a=3) (which always yields a nonzero,
and hence true in C, value) when you meant if(a==3),
but the former is not an error and cannot be rejected.

I agree Ada, which treats assignment as a statement not
an expression, could and should be more "type"safe here.
FWLIW if unifying valued and nonvalued subprograms
were going to be done, I would prefer the PL/1 approach:
include the RETURNS clause with a real type, or omit it
for a nonvalued procedure, rather than making void a type.

It is also true that C implementations are not required to,
and normally don't, check that the declared (return and
argument if any) types in a referencing "unit" (source file)
agree with those in a definition=body in a different one,
unless you (redundantly) repeat the declaration, which is often
done by the .c #include'ing the .h for precisely this reason.
(Even then to ensure parameter types are checked you must
use the "new" in C++ and C89 -- and more Pascal/Ada-like --
"prototype" syntax rather than the original K&R1 syntax.)
But that is true for all types, not just void.

--
- David.Thompson 1 now at worldnet.att.net






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

* Re: Side-Effects in Functions [Rosen Trick]
  2001-11-22  6:22   ` David Thompson
@ 2001-11-23  7:18     ` Brian Rogoff
  0 siblings, 0 replies; 28+ messages in thread
From: Brian Rogoff @ 2001-11-23  7:18 UTC (permalink / raw)


On Thu, 22 Nov 2001, David Thompson wrote:
> Brian Rogoff <bpr@shell5.ba.best.com> wrote :
> > It's called void, not null. The problem with C is that it ignores returned
> > value types so even though it has void it doesn't really use it. I imagine
> > a reworked Ada would only allow void returning function/procedure values
> > to be ignores, and so wouldn't lose type safety.
> >
> I'm not sure what you were trying to say there.
[...snip...]
> What you may be after is that the value of any non-void expression
> in C, whether it is the return from a function or not, is discarded
> if that expression constitutes an entire statment.  

This is exactly what I was trying to say, thanks. In ML, an expression
oriented language, things separated by ";" must return unit (which is like
void) so you can't just ignore the results of functions unless you
explicitly request to do so. If we got rid of the function/procedure
distinction in an Ada like language then we'd do things this way I think.

-- Brian





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

end of thread, other threads:[~2001-11-23  7:18 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-11-05 21:10 Side-Effects in Functions [Rosen Trick] Alexandre E. Kopilovitch
2001-11-05 21:58 ` Brian Rogoff
2001-11-22  6:22   ` David Thompson
2001-11-23  7:18     ` Brian Rogoff
  -- strict thread matches above, loose matches on Subject: below --
2001-11-02  3:56 List container strawman Ted Dennison
2001-11-02  7:28 ` Ehud Lamm
2001-11-02 15:06   ` Ted Dennison
2001-11-02 15:32     ` Marin David Condic
2001-11-02 16:33       ` Ted Dennison
2001-11-02 16:43         ` Marin David Condic
2001-11-02 22:51           ` Jeffrey Carter
2001-11-03  0:24             ` Matthew Heaney
2001-11-03  2:21               ` Jeffrey Carter
2001-11-03 22:51                 ` Rosen Trick [List container strawman] Nick Roberts
2001-11-04 13:07                   ` Robert Dewar
2001-11-04 17:17                     ` Side-Effects in Functions [Rosen Trick] Nick Roberts
2001-11-05  2:46                       ` Robert Dewar
2001-11-05  7:26                         ` pete
2001-11-05 10:29                           ` Dmitry A. Kazakov
2001-11-05 11:19                             ` pete
2001-11-05 14:59                               ` Dmitry A. Kazakov
2001-11-05 15:21                                 ` Preben Randhol
2001-11-05 16:04                                   ` Ted Dennison
2001-11-05 16:33                                   ` Dmitry A. Kazakov
2001-11-05 17:42                                     ` Warren W. Gay VE3WWG
2001-11-05 18:11                                       ` Preben Randhol
2001-11-06  8:38                                       ` Dmitry A. Kazakov
2001-11-06  9:31                                         ` tgingold
2001-11-06  0:10                             ` Nick Roberts
2001-11-06  9:30                               ` Dmitry A. Kazakov
2001-11-06 20:08                               ` Florian Weimer
2001-11-06 22:48                                 ` Nick Roberts
2001-11-07 10:46                                   ` Florian Weimer
2001-11-05 13:56                           ` Robert Dewar
2001-11-05 16:08                             ` Ted Dennison
2001-11-05 17:44                               ` Warren W. Gay VE3WWG
2001-11-05 15:56                         ` Ted Dennison
2001-11-05 18:46                         ` Nick Roberts
2001-11-08 11:51                           ` Georg Bauhaus

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