From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,8e64f4db20d57eb5 X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Call by reference vs. call by value Date: 1996/07/22 Message-ID: X-Deja-AN: 170634284 references: <31F10E50.726@egr.uri.edu> organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-07-22T00:00:00+00:00 List-Id: In article , Felaco wrote: >Of course I have to admit ignorance here. I never really thought >about it in Ada. For some reason I assumed that the compiler would in >some way ensure that this type of error would not occur, either by >passing the array by value, or reordering the assignments so the >problem would not occur. I realize I expected too much. You're not alone -- I've heard many professional Ada programmers who are surprised at the rule, or are surprised that there's a difference between by-copy and by-reference. That makes me nervous about this particular implementation dependence. >Well, I guess I never conceived a machine might exist where call-by- >value for anything bigger than a word is more efficient than call by >reference, Well, a word, or maybe 2 or 3 words -- it depends, for example, on how many machine registers are lying around. But that's basically right, call-by-value is more efficient for small-ish things. But machines have different word sizes. And it's not clear what fits in a word, even when you know the word size. For example, suppose I have a record containing 4 Character components (not packed). Some compilers will allocate 4 words, some will allocate 4 bytes -- it depends on the machine, and to some extent on the whim of the compiler writer. >... so my first instinct would be to dictate that >call-by-reference be used in all cases. All cases? Surely you don't mean *all*. Surely you want scalars passed by copy (in a register, normally). Maybe you meant "all array/record cases"? Well, that solves the implementation dependence problem, but it's less efficient. A packed array of 32 booleans fits in a word, and I would like it to be passed by copy, in a register. Also, Robert Dewar pointed out elsewhere the problem with passing components of packed objects (record-within-record, for example) by reference, when they're not byte-aligned. And slices. >... I believed the opposite was >true, however, because I wrongly thought that the designers of Ada >valued safety over performance, which is not really true. Right, the designers made trade-offs, and this is one that went in favor of efficiency over safety. (As I said elsewhere, I suspect it's possible to get both, but not simple.) >> The question is, does someone who knows Ada get into trouble with >> this rule? Clearly if you don't know a rule in the language you can >> always get into trouble, you can't expect Ada to automatically >> correct your misconceptions about the language. This is certainly a >> lesson that you need to know a language well to avoid trouble, but >> it is not convincing that there is a problem here. This is the standard argument that gets trotted out in favor of all manner of C pitfalls -- "the programmer should know the language". True, but unfortunately, many programmers do not know their language that deeply, and even ones who do make mistakes. I don't buy it in the C case, and I don't buy it in this particular Ada case. C has many things that are officially undefined, but programmers don't know that, or don't notice it in particular cases, and write non-portable and/or buggy code. Ada has just a few undefined things, so the problem is less severe, but it's still a problem. >Of course one should know a language well, but in this case the >language "wasn't very friendly". I agree. My answer is, "Yes it's unfriendly/unsafe, but it's an efficiency trade-off, and efficiency is important, too." >For the record, my recommendation is simply to clarify the issue. Well, the RM is pretty clear on this point, I think. >It would be nice if there were no implementation defined behavior, in >a perfect computer world, but I'm not that naive. I agree. It should be a language design goal to eliminate implementation dependence. However, it's not always feasible to do so. For example, how could you eliminate the implementation dependence inherent in delay statements? >One possibility that hasn't been explored is this: define the rule as >call-by-value *by default*, and give me a pragma or something to get >the more efficient call-by-reference behavior. Then I would be forced >to be aware of the pitfalls. It's not the greatest solution, but it >least it gives the programmer more control. Yes, that's one reasonable solution. It shouldn't be a pragma, but should use some sensible syntax. Some Pascal compilers do something like this -- there are by-value parameters, and CONST parameters (which are by-reference, but still in-mode), and VAR parameters (which are by-ref/in-out). Maybe CONST parameters are part of standard Pascal now; I don't know. Anyway, this solution has some problems (passing of components of packed things, forcing the programmer to specify something that *usually* doesn't matter, ..) The SPARK subset of Ada solves the problem by making sure you can't write code that can tell the difference between by-copy and by-ref. In particular, exception handling is not allowed, and aliasing of parameters is not allowed. This leads to a pretty restricted version of the language, though. - Bob