From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 17 Mar 93 23:58:31 GMT From: eachus@mitre-bedford.arpa (Robert I. Eachus) Subject: Re: Function call or variable? Message-ID: List-Id: Adam Beneschan makes some good points, but a language lawyer like me has to argue the details... > The semantics aren't entirely the same---there are important > differences between constants and parameterless functions. For > example, you can use a constant in a CASE selector, but not a > parameterless function. There are other contexts in Ada where > constant expressions are required; in this case, constant may appear > while parameterless functions may not. Fooled you. Enumeration and character literals ARE parameterless functions which can appear as case selectors. There are also functions which have the form of an attribute, but they are not parameterless. i. e. T'LAST(2). > The obvious difference between variables, arrays, and function > calls, is that you can put variables and arrays on the left side of > an assignment (or pass them as OUT or IN OUT parameters). Gotcha again... A function which returns an access value can appear on the left hand side of an assignment statement: type R is record C: Character; I: Integer; end record; type RA is access R; V: R; -- a variable of type R. function F return RA; -- a function which returns an access value. ... V.I := 3; -- no surprise. F.C := 'V'; -- ain't Ada fun? The same is true with array types for subscripts and slices. > Changing from a parameterless function to and from a constant > doesn't have this property---the identifier's class changes and > some of the semantics change with it. The biggest change, which programmers tend to forget, is that functions are overloadable, variables are not. So you can have the cases where as a result of changing a declaration in one package, a function in another package is no longer directly visible. > If a package makes a constant value publicly available, but the program > designer anticipates that the program may change later such that the > value won't be a constant any more, I would strongly argue that the > value should be implemented as a parameterless function from the > beginning. The function's body will be trivial if the value is a > constant, but when the program is modified later, only the function > body needs to be changed. The package spec won't change at all, and > this is the best way to guarantee that the remainder of the program > will not have to change just because the implementation of this one > value changes. There won't be any loss of efficiency if you use > PRAGMA INLINE (and your compiler supports it). This, I think, is the > logical parallel to private types. Good idea. Especially given the gotcha above. > Not necessarily. You could use #define to ensure that the program is > changed in only one place. I don't believe I've ever seen any C code > that's designed like this, though. No, no, no. I have seen C code like this, and I have seen people use #defines to change things. And I have seen the code compile cleanly and work in simple cases but break horribly later. For example, the code in the #define for example might use a local variable, and you only get burned if the #define is used in a scope where there is a variable of the same name. But the burn occurs at run time, and in the form of a wrong answer. > What's a little amusing about this is that, in my opinion, none of > these design arguments were actually factors in how the language > syntax was decided on. I don't have any evidence to back this up, > but I'm willing to bet that parameterless procedures are the way > they are in Ada because they were that way in Ada's ancestors, > Pascal and Algol. C's syntax was probably designed to make it easy > for the compiler's parser. You lose! In Ada 80, parameterless functions did have empty parentheses. June 80 RM, section 6.5: function_call ::= _function_name actual_parameter_part | _function_name () This was changed during the ANSI standardization process. Although one argument if favor of the change was that the empty parentheses were ugly, the telling arguments were the unification of the syntax, and allowing the enumeration literals are function calls simplification. > Back in the early 80's, when Ada was in the design process, I remember > reading an article by someone who pointed out the advantages of having > function calls and array references have the same syntax---both use > parentheses, while in other languages array references use square > brackets. However, this clearly had nothing to do with the real > reason array references use parentheses; the real reason is that > EBCDIC doesn't have square brackets. This made the article seem like > a lame, after-the-fact rationalization, even though it did make some > valid points. Wrong again. The allowed characters come from the Steelman requirements and not from EBCDIC. (Although they do trace to the IBM 029 card punches.) If common to EBCDIC and ASCII had been the requirement, there would have been lots of choices. But the justification was NOT a lame after the fact one. It was a lot of effort but strongly desired by those who had made exactly that change in existing code in other programming languages. (Embedded systems often make this time/space tradeoff very late in the design process. The intent in designing Ada was that 1) it not be an expensive change to make and 2) to the greatest extent possible it should not be necessary to change the code. Thus inlining of function calls with static arguments should be the same as doing the array reference in place. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...