* 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 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
* List container strawman @ 2001-11-02 3:56 Ted Dennison 2001-11-02 7:28 ` Ehud Lamm 0 siblings, 1 reply; 28+ messages in thread From: Ted Dennison @ 2001-11-02 3:56 UTC (permalink / raw) Since we do seem to be reaching a small amount of agreement on details, I went ahead a put together a strawman package spec (sans private part) for the unbounded list container, for the purposes of keeping the dicussions rolling in a postitive direction. It is attached here, and available on my website at http://www.telepath.com/dennison/Ted/Containers-Lists-Unbounded.ads.html . If it is close enough to be worth persuing, we may be able to use it as a starting point. (Note: The htmlization there was done by a tool I'm developing as part of the next release of OpenToken. If you have comments on the job it did, I'd like them too, but email would probably be the best venue for it). --- 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: List container strawman 2001-11-02 3:56 List container strawman Ted Dennison @ 2001-11-02 7:28 ` Ehud Lamm 2001-11-02 15:06 ` Ted Dennison 0 siblings, 1 reply; 28+ messages in thread From: Ehud Lamm @ 2001-11-02 7:28 UTC (permalink / raw) Thanks fro the effort. Sorry I didn't have time these past week to contribute anything. A few questions/comments. I am not sure about many of these. 1. In my scheme "Element" is a generic parameter of the top package (Containers), and not of the specific implementations. (Remember, my attemp for having interface inheritance) 2. Why is List private? Shouldn't it be limited private, so we avoid possible erros caused by aliasing? We may need a private implementation, but I'd prefer this not to be the default, since it can come and bite you when you don't know what you are doing. The private version is for library builders and more advanced users, best used as part of a layered design that hides the list itself. (If the majority wants private, at least the spec should mention the possbile problems) 3. "Construct" is indeed a long name. We can, as part of the library, decide on some standard name for this like - or + 4. I've seen many implemenations that paremtrize Insert and Remove with a direction parameter, instead of having seperate routines (_Back/_Front). I am not sure I know which approach I prefer... 5. Front() and Back() raise execption on Empty List? 6. I like having a "No_More_Elements()" operation as part of the Iterator interface. It saves time compared to Size (for containers that don't keep count of size), and I don't like programming with exceptions ("exceptions for control flow"). 7. Sort should be in a child unit. Finally, a more general question: Is this a DeQueue or a Doubly-linked list? Should these be two different abstractions? (IMO: Yes, they should). Ehud ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: List container strawman 2001-11-02 7:28 ` Ehud Lamm @ 2001-11-02 15:06 ` Ted Dennison 2001-11-02 15:32 ` Marin David Condic 0 siblings, 1 reply; 28+ messages in thread From: Ted Dennison @ 2001-11-02 15:06 UTC (permalink / raw) In article <9rti6v$hcu$1@news.huji.ac.il>, Ehud Lamm says... >1. In my scheme "Element" is a generic parameter of the top package >(Containers), and not of the specific implementations. >(Remember, my attemp for having interface inheritance) I didn't do that because that is precisely what Booch does that makes it so complicated to use. If one does that, then proper use of the package would require 3 cascading generic package instantiations. If that is OK, then in my opinion we should just bag this whole thing and use Booch. >2. Why is List private? Shouldn't it be limited private, so we avoid >possible erros caused by aliasing? First off, I'd like to note for anyone who may have missed it, that any Element passed in to be put on a list or taken off of one will be *copied*. Pointers to elements will not be used. If List were limited private, then we'd have to get rid of all those "&" routines. My thinking was that Lisp-like functional list processing would be desirable. You could indeed have aliasing problems, but only if your Element type uses pointers. Having "&" avaliable also makes list operations somewhat consistent with arrays, which also have "&". However, any use of those "&" routines will involve creating a copy of every element (much like using "&" with arrays does). That would probably be too expensive in most cases, so perhaps it really isn't all that valuable. I'm curious how others feel about this. >(If the majority wants private, at least the spec should mention the >possbile problems) I can agree with this. At the least there should be some sort of warning in there about using pointers in Element with those routines. >3. "Construct" is indeed a long name. We can, as part of the library, decide >on some standard name for this like - or + As the comment said, I seriously considered that. However, it is not (yet) a common idiom to use those for constructors. So I'm not sure if it would help or hurt readability. Again, I'm curious what people think about this. >4. I've seen many implemenations that paremtrize Insert and Remove with a >direction parameter, instead of having seperate routines (_Back/_Front). I >am not sure I know which approach I prefer... >5. Front() and Back() raise execption on Empty List? Assuming you are talking about the iterator routines "First" and "Last", that's a good point. I seem to have totally neglected that case, and thus left serious problems in there. For instance, the comment that says "For an empty list, First = Last." is clearly wrong. That would indicate a list with one element, not an empty one. I'll have to redo the iterators somehow... >6. I like having a "No_More_Elements()" operation as part of the Iterator >interface. It saves time compared to Size (for containers that don't keep >count of size), and I don't like programming with exceptions ("exceptions >for control flow"). That seems sensible. And I agree about using exceptions, which is why it is only one example of 3. That stuff is all wrong anyway though... >7. Sort should be in a child unit. Why do you feel that way? What does putting it off in a separate unit gain you? > >Finally, a more general question: >Is this a DeQueue or a Doubly-linked list? Should these be two different >abstractions? (IMO: Yes, they should). What specificly would the difference be? Clearly it would have to be doubly-linked to support all those push and pop operations, and both Next and Previous as iterators. You could implement those on a singly-linked list, but it wouldn't be very efficient. --- 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: List container strawman 2001-11-02 15:06 ` Ted Dennison @ 2001-11-02 15:32 ` Marin David Condic 2001-11-02 16:33 ` Ted Dennison 0 siblings, 1 reply; 28+ messages in thread From: Marin David Condic @ 2001-11-02 15:32 UTC (permalink / raw) O.K. I hereby revoke my agreement with Limited Private. If the List type works kind of like the Ada.Strings.Unbounded.Unbounded_String type, then I guess we're O.K. (Lists do look an awful lot like Ada.Strings.Unbounded, don't they? You could view an unbounded string kind of as a list of characters, eh? Maybe look at A.S.U for ideas about how it should look and what sort of operations it should have?) How is assignment handled here? If you don't inherit from Ada.Finalization how do you make sure you copy the list rather than duplicate pointers to the list? (Assuming the underlying implementation relies on pointers to list elements.) MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com Web: http://www.mcondic.com/ "Ted Dennison" <dennison@telepath.com> wrote in message news:1EyE7.10050$xS6.13527@www.newsranger.com... > > First off, I'd like to note for anyone who may have missed it, that any Element > passed in to be put on a list or taken off of one will be *copied*. Pointers to > elements will not be used. > > If List were limited private, then we'd have to get rid of all those "&" > routines. My thinking was that Lisp-like functional list processing would be > desirable. You could indeed have aliasing problems, but only if your Element > type uses pointers. Having "&" avaliable also makes list operations somewhat > consistent with arrays, which also have "&". > > However, any use of those "&" routines will involve creating a copy of every > element (much like using "&" with arrays does). That would probably be too > expensive in most cases, so perhaps it really isn't all that valuable. I'm > curious how others feel about this. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: List container strawman 2001-11-02 15:32 ` Marin David Condic @ 2001-11-02 16:33 ` Ted Dennison 2001-11-02 16:43 ` Marin David Condic 0 siblings, 1 reply; 28+ messages in thread From: Ted Dennison @ 2001-11-02 16:33 UTC (permalink / raw) In article <9rue9f$j4t$1@nh.pace.co.uk>, Marin David Condic says... >How is assignment handled here? If you don't inherit from Ada.Finalization >how do you make sure you copy the list rather than duplicate pointers to the >list? (Assuming the underlying implementation relies on pointers to list >elements.) Well, the honest answer is that I hadn't thought of that. :-( I guess if the funcional stuff is going to remain in there, then it will have to be a controlled type. That means that users won't be able to instantiate it from within a subprogram (yuk!). If we *do* make it limited, then another issue I just thought of is that we wouldn't be able to make lists of lists (we had already decided that we won't allow limited list components). However, I can't think of a good common use for lists of lists of the top of my head. --- 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: List container strawman 2001-11-02 16:33 ` Ted Dennison @ 2001-11-02 16:43 ` Marin David Condic 2001-11-02 22:51 ` Jeffrey Carter 0 siblings, 1 reply; 28+ messages in thread From: Marin David Condic @ 2001-11-02 16:43 UTC (permalink / raw) If the List type is simply private, can it contain an element that is Controlled? In other words, is this a problem that can be covered up with just one more layer of indirection? I'm guessing that Ada.Strings.Unbounded has to do *something* fairly dynamic in its underlying implementation and it has to solve the problem of assignment along the way. That either means a) the problem can be solved from within the language or b) its done with smoke and mirrors behind the scenes. I'm guessing that A is likely to be the case, so perhaps a solution does exist? MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com Web: http://www.mcondic.com/ "Ted Dennison" <dennison@telepath.com> wrote in message news:wVzE7.10194$xS6.14029@www.newsranger.com... > > I guess if the funcional stuff is going to remain in there, then it will have to > be a controlled type. That means that users won't be able to instantiate it from > within a subprogram (yuk!). If we *do* make it limited, then another issue I > just thought of is that we wouldn't be able to make lists of lists (we had > already decided that we won't allow limited list components). However, I can't > think of a good common use for lists of lists of the top of my head. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: List container strawman 2001-11-02 16:43 ` Marin David Condic @ 2001-11-02 22:51 ` Jeffrey Carter 2001-11-03 0:24 ` Matthew Heaney 0 siblings, 1 reply; 28+ messages in thread From: Jeffrey Carter @ 2001-11-02 22:51 UTC (permalink / raw) Marin David Condic wrote: > > If the List type is simply private, can it contain an element that is > Controlled? In other words, is this a problem that can be covered up with > just one more layer of indirection? There's no problem with the actual type being Controlled if the formal type is [limited] private. If there's anything about the actual type that requires finalization we would hope the client would implement it as a controlled type, since objects of this type are going to come and go as items are added and removed from the structure. > > I'm guessing that Ada.Strings.Unbounded has to do *something* fairly dynamic > in its underlying implementation and it has to solve the problem of > assignment along the way. That either means a) the problem can be solved > from within the language or b) its done with smoke and mirrors behind the > scenes. I'm guessing that A is likely to be the case, so perhaps a solution > does exist? Unbounded_String may be implemented as a controlled type. It's implementation is not defined, so compiler writers may use any tricks they think necessary, but you could write the implementation in plain Ada. Another place where some compiler writers use tricks is the interaction between a random number Generator value and the Random function. The generator holds the state data for the algorithm, which are supposed to be updated when a number is generated. You can implement Generator as a controlled type with a pointer to the state data, but again other tricks are possible from within the compiler. -- Jeffrey Carter ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: List container strawman 2001-11-02 22:51 ` Jeffrey Carter @ 2001-11-03 0:24 ` Matthew Heaney 2001-11-03 2:21 ` Jeffrey Carter 0 siblings, 1 reply; 28+ messages in thread From: Matthew Heaney @ 2001-11-03 0:24 UTC (permalink / raw) "Jeffrey Carter" <jeffrey.carter@boeing.com> wrote in message news:3BE3235D.E292B890@boeing.com... > Another place where some compiler writers use tricks is the interaction > between a random number Generator value and the Random function. The > generator holds the state data for the algorithm, which are supposed to > be updated when a number is generated. You can implement Generator as a > controlled type with a pointer to the state data, but again other tricks > are possible from within the compiler. Why would you need to implement type Generator as a Controlled type? Generator state is allocated on the stack, so Finalization is not required. Allocating state on the heap and using Controlled Finalization would be a horribly inefficient way to implement that type. No heap allocation or compiler magic is needed to implement Generator; just use the Rosen Trick: package P is type Generator is limited private; function Random (G : Generator) return Integer; private type Handle_Type (G : access Generator) is null record; type Generator is limited record Handle : Handle_Type (G'Access); State : State_Type; --whatever end record; end P; package body P is function Random (G : Generator) return Integer is State : State_Type renames G.Handle.G.all; begin -- modify State as necessary return X; end; end P; This is all perfectly legal. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: List container strawman 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 0 siblings, 1 reply; 28+ messages in thread From: Jeffrey Carter @ 2001-11-03 2:21 UTC (permalink / raw) Matthew Heaney wrote: > > "Jeffrey Carter" <jeffrey.carter@boeing.com> wrote in message > news:3BE3235D.E292B890@boeing.com... > > Another place where some compiler writers use tricks is the interaction > > between a random number Generator value and the Random function. The > > generator holds the state data for the algorithm, which are supposed to > > be updated when a number is generated. You can implement Generator as a > > controlled type with a pointer to the state data, but again other tricks > > are possible from within the compiler. > > Why would you need to implement type Generator as a Controlled type? > Generator state is allocated on the stack, so Finalization is not required. > Allocating state on the heap and using Controlled Finalization would be a > horribly inefficient way to implement that type. The obvious way to modify an in parameter is to have it be an access value and change what it points to. You would want this to be Controlled so you could deallocate the storage when an object of the type goes out of scope. The GNAT implementation says -- The design of this spec is very awkward, as a result of Ada 95 not -- permitting in-out parameters for function formals (most naturally -- Generator values would be passed this way). In pure Ada 95, the only -- solution is to use the heap and pointers, and, to avoid memory leaks, -- controlled types. > > No heap allocation or compiler magic is needed to implement Generator; just > use the Rosen Trick: Yes, that is a trick that can be used (although your example has a couple of errors). Was it known before standardization? I somehow suspect it would have been outlawed if it were. GNAT uses type State is ... type Generator is limited record Gen_State : State; end record; Following the above quote, they add -- This is awfully heavy, so what we do is to use Unrestricted_Access to -- get a pointer to the state in the passed Generator. This works because -- Generator is a limited type and will thus always be passed by reference. type Pointer is access all State; function Random (Gen : Generator) return Uniformly_Distributed is Genp : constant Pointer := Gen.Gen_State'Unrestricted_Access; and then modify Genp.all. Since 'Unrestricted_Access is an implementation-dependent attribute, I think this qualifies as a trick, too. I wonder if there is some advantage to this trick over the Rosen trick. -- Jeff Carter "Now go away or I shall taunt you a second time." Monty Python & the Holy Grail ^ permalink raw reply [flat|nested] 28+ messages in thread
* Rosen Trick [List container strawman] 2001-11-03 2:21 ` Jeffrey Carter @ 2001-11-03 22:51 ` Nick Roberts 2001-11-04 13:07 ` Robert Dewar 0 siblings, 1 reply; 28+ messages in thread From: Nick Roberts @ 2001-11-03 22:51 UTC (permalink / raw) I've always felt that this whole charade is an academic Alice-in-Wonderland adventure. The right solution, of course, is to use a procedure (with an in-out parameter) instead of a function. Grrr. PS: Why? Because functions should not have side-effects (in a language like Ada). I don't care about expediencies that are to do with debugging, profiling, auditing, and that sort of thing (where the effort of not using functions would be silly), but where the main thrust of the logic has a side effect, use a procedure! Good programming (in Ada) is not about what weird and funny things you can do that will catch people by surpise (and so be likely to cause bugs, or angst, or both). PPS: I don't think allocating an RNG state block on the heap, rather than the stack, is likely to have much effect on speed; surely the burden of indirect access would be vastly outweighed by the burden of computation for each number generation cycle? And why would using finalisation be inefficient? -- Nick Roberts ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Rosen Trick [List container strawman] 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 0 siblings, 1 reply; 28+ messages in thread From: Robert Dewar @ 2001-11-04 13:07 UTC (permalink / raw) "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. Here are the facts: Ada permits functions to have side effects, and does not attempt to prohibit side effects in functions (an odd and inconsistent exception is functions in protected types, and that was indeed a major discussion point in the design) 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. 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. 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. 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 I have never understood the rationale for this inconsistent design. When I talk to someone like Tuck, who basically supports the prohibition, it seems to come from a general feeling that functions should not have side effects. OK, but that's some other language than Ada, where functions are permitted to have side effects. 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. 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. 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, 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. 2. Those who really don't like functions with side effects much, but would tolerate IN OUT parameters if they had to, but are certainly not going to fight for them, and would vote no or abstain. I think I correctly label Tuck and the design team in this second group, which is also fairly large. 3. Those who really find this restriction annoying, and have fought to get it lifted. They are a large group, but somewhat less than a working majority. I don't see anything that would put group 3 in a position to fix this annoying restriction in the near future, so it to me is just a minor defect in the language that will stay uncorrected, but we can live with it, it's not fatal, just very annoying. ^ permalink raw reply [flat|nested] 28+ messages in thread
* 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 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 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 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 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 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 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-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-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 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 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 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 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 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 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 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
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