with Ada.Text_IO;
procedure test1 is
procedure p1(a : integer := 1; b : Integer := 2) is
begin
Ada.Text_IO.Put_Line("a,b: " & a'Image & b'Image);
end p1;
begin
p1(5);
-- the original intention was to give b the value 5 but "a" stole it when introduced :-)
end test1;
I have several times modified subroutines and forgotten to check how I have used them. I would prefer that the compiler gave me a hint here.
Necessary only when types are same, which is suspicious on its own. Otherwise it is impossible to make an error.
I usually switch to keyed notation when the call occupies more than one source code line,
This is the standard behavior Iād expect for languages which have default arguments (python, C++, ruby) ā arguments passed fill left to right. You can avoid it by using named arguments, but adding defaults to existing functions is a known issue for those without it.
No, this is not an Ada gotcha, per se..
This is essentially the equivalent of saying āhand me thatā and pointing to something, the pan of beans and the teapot both in the line of your pointing, and then getting upset that someone hands you the wrong one even though you were pointing at both.
To do what your comment indicates you want, be specific, say P1( B => 5 );.
Iāve seen style rules that require named notation if two or more arguments have the same type
This is the rule that I personally follow. Whenever I find myself passing two parameters of the same type, one after another, a little bell goes off in my head and I switch over to named notation. In fact I generally try to avoid designing subprograms with two formal parameters in a row with the same type.
The other rule I follow is to use named notation for every parameter that has a default value.
And then the simplest rule is to just use named notation everywhere ā¦
That really depends, if you designed it with the defaults, all/majorly up-front design, testing/verifying, the chance isnāt too highā¦OTOH, if youāre seat-of-you-pants/iterative developing, much higher.
The issue is essentially this:
Procedure Example( X, Y, Z : Integer ); -- Rev. 1
Procedure Example( X, Y : Integer ); -- Rev. 2
Procedure Example( X : Integer ); -- Rev. 3
Thereās three procedures here, they could be the same (feeding default values into the overloaded procedure with fewer parameters), or they could be different. Whereas with Procedure Example_2( X, Y : Integer:= 1; Z : Integer := 0 ); you know exactly that the former is happening for all permutations. ā The feature (default parameters [or even overloading]) is not a bad feature, itās not even particularly error-prone (see this story; the only bug was because someone he queried for the proper sequence guessed instead of checking the information).
The TL;DR here is this: if you are being bitten by defaults even semi-regularly, then it means that you are not spending enough time designing, because those bugs only happen when the design is fluctuating.
No, not really.
Itās not āthe blame gameā to acknowledge that (1) a ever-fluctuating āsoftā design will be inconsistent, and (2) changing said design impacts how things interact.
An additional advantage of using named arguments is that client code becomes shielded against (same type) formal arguments being shifted around at unsuspecting moments by some maintainer who decides a different declaration order is clearly more coherent and long overdue..