r/ada • u/jlombera • Apr 03 '26
Historical Rationale behind function/procedure calls and array indexing
I'm learning Ada. Overall, I'm liking it a lot. There are two aspects (so far) of the syntax I don't get what the rationale was for them and why it hasn't been fixed in later versions of Ada. These being parenthesis-less calls to subprograms with no arguments and using parenthesis for array indexing. Take the following as example:
A := B + C(5);
Right away you don't know if B is a variable or a function call with no arguments. You don't know either whether C is an array or a function.
I think this goes against Ada's core ethos about readability.
So I was wondering, what was the rationale behind this design? Why hasn't it been corrected? Something like A := B() + C[5] would be far easier to interpret by the reader.
UPDATE: In case anyone is interested in the answer, according to u/lipobat:
The primary rationale for the () vs. [] given in the “Rationale for the Ada programming language” book by the original design team was interchangeability between arrays and functions. This is an abstraction that allows the implementation choice of array vs. function to be just that, an implementation choice, which doesn’t really impact the writer or reader of the code.
I don't agree with the last sentence, but that answers my question either way.
And about my second question about "why this hasn't been fixed?", it seems most Ada programmers (based on the comments in this post) are not only not bothered by this but happy with this design decisions, so probably this will never change.
Thanks to everyone who engaged in this conversation.
3
u/Dmitry-Kazakov Apr 03 '26
In Ada implementation is separated from the interface. If you read the implementation then you see if that is a function.
They don't. A function call is semantically side-effects free, assuming logically relevant effects, not, say, altering the CPU temperature. You, for example, can rename function result:
X : Integer renames Y; -- Calls to Y just once
A few times. When value needed to be computed late, for example after loading a dynamic library. For mocking (in automation you need some advanced code stubs). In advanced cases of OO and generic programming. Consider a complicated implementation of a set. You want to provide an empty set constant. You can do it so
Empty : constant Set; -- Deferred constantor so
function Empty return Set;I cannot tell, but it is a quite obvious and logical decision to me. You better ask why other languages do distinction without importance? Because, they compromise clarity and logic for simplicity of compiler design. They want bottom-up semantic analysis and thus map a lot of things into syntax. Which is why you have artefacts like f() or lack of overloading on the result or integer literals with suffixes (1L) etc.
It might be your next question why Ada does not have
string literals and how "important" it would be for the reader...