4 ms·
WRT "out" parameters, it means that very literally. There the variable is only passed out, it is not passed "in." Steve's test never assigns "A" in Foo() so "A"
by gvb 8y ago
WRT "out" parameters, it means that very literally. There the variable is only passed out, it is not passed "in." Steve's test never assigns "A" in Foo() so "A" is an uninitialized variable that then gets stored in the mainline "A" (which has the same name, but is an entirely different variable). The mainline "A" is assigned the value 12 but then gets overwritten by the uninitialized value passed out by Foo().
with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : out Integer) is
begin
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Foo(A);
end Outp;
A clearer example would be:
with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : out Integer) is
begin
Put_Line (Integer'Image (A)); -- Uninitialized variable, random value
A := 42;
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Put_Line (Integer'Image (A));
Foo(A);
Put_Line (Integer'Image (A));
end Outp;
This will still give the uninitialized variable warning (typically can and should configure the compiler to turn that into an error, not a warning).
Playing compiler, the output should be
12 -- Outp()
<random value> -- Foo()
42 -- Foo()
42 -- Outp()
You can make variables in and out by saying that (literally). This will do what Steve expected:
with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : in out Integer) is
begin
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Foo(A);
end Outp;
- 0xDEEPFAC 8y agoAlso, added in a recent version of the language (as part of 2020) you can simply use 'Image directly on an object saving you a bit of typing : ). And let me let you in on a secret Ada programmers don't talk about or put in examples - you don't have to type the Identifier at the end of the procedures! with Ada.Text_IO; use Ada.Text_IO; procedure Outp is procedure Foo (A : in out Integer) is begin Put_Line (A'Image); end; A : Integer := 12; begin Foo (A); end;
- thestoicattack 8y agoOoh, I like that new 'Image usage. I was told that adding the identifier to the end of blocks is just a good practice, since the compiler can tell you if you misread the nesting and wrote the wrong name.
- gliptic 8y agoI think Steve is reacting more to this not being a compile error.
- steveklabnik 8y agoYes, the text explained how I should write this, my surprise is that I can get undefined behavior. And that the text says that this may, but is not guaranteed to, warn. On Twitter the other day, someone suggested that this is because, when Ada was first made, this kind of analysis was truly to expensive, and so the guarantee was not made, and they're sticking to backwards compatibility, and modern implementation should basically always warn. That seems reasonable, but I have no idea if it's correct. I assume most real-world Ada scenarios treat warnings as errors.
- sanxiyn 8y agoYes, the analysis is called definite assignment analysis: https://en.wikipedia.org/wiki/Definite_assignment_analysis https://en.wikipedia.org/wiki/Definite_assignment_analysis It was a great victory of Java and C# to require this. Java's analysis is "buggy" and C#'s is complete.
- twic 8y agoTo be clear, buggy in that it can sometimes not detect correct assignment, and require you to add some unnecessary assignments to shut it up. Not in that you can ever read an uninitialised variable. That is a bit of a theme in Java. The type inference often has the same problem. (Although the type inference is also actually unsound)
- kqr 8y agoHub, is that supposed to not be the case with C#? Because I've definitely had that experience at least once, of knowing a variable is initialized and the compiler not "getting" it until I added some semantically redundant formality.
- 8y ago