Why is named association required for a one-element record aggregate? - record

When an aggregate contains only one element, as below, positional notation results in a compilation error and we have to use named notation only. Why?
type singleton is record
v : integer;
end record;
v1 : singleton := (0);
results in the compiler message
check.adb:6:23: positional aggregate cannot have one component
check.adb:6:23: write instead "V => ..."
gnatmake: “check.adb" compilation error
whereas this is OK:
v2 : singleton := (v => 0);

Parentheses round an expression are redundant, so (0) = 0 and it's an integer not an array aggregate.
So, for the special case of a one-element aggregate, named association is required to distinguish an aggregate from a simple value.
Contrast this with (0,0) which can only be an aggregate; therefore there is no ambiguity.
Even though in the context of the question, it's obvious to a human programmer which is intended, that will not always be the case.
Consider a one-element aggregate in a multi-dimensional array which is one field of a record; there can be ambiguities that the compiler cannot resolve (at least, before reading a whole lot more of the source file!) and would make life pretty difficult for anyone reading the program.

You don't have to use named notation.
v1 : singleton := (others => 0);
This will assign 0 to all elements in v1 and the compiler will know that is not a number but an array instead.
If the record happen to have different types you could use
v1 : singleton := (others => <>);

Related

Sigilless variables, constants, bindings: when to choose what

So, from the documentation is almost clear what the three entities from the title are, but it is not very clear what their purpose is.
Constants are common in many languages. You don't want to write 3.14 all over your code and that's why you define a constant PI that, by the nature of the thing it represents, cannot be changed and that's why its value is constant in time.
Defining a variable bound to another entity with := is also almost clear but not really. If I bind a variable to 3.14, isn't it the same as defining a PI constant? Is $a := $b actually defining $a as an alias to $b or, as some other languages call it, a reference? Also, references are generally used in some languages to make it clear, in object construction or function calls, that you don't want to copy an object around, but why would it be useful, in the same scope, to have
$number_of_cakes = 4;
$also_the_number_of_cakes := $number_of_cakes;
?
Finally, the documentation explains how one can define a sigilless variable (that cannot be varied, so, actually, yet another kind of constant) but not why one would do that. What problems do sigilless variables solve? What's a practical scenario when a variable, a constant, a binding variable do not solve the problem that a sigilless variable solve?
Constants are common in many languages. You don't want to write 3.14 all over your code and that's why you define a constant PI that, by the nature of the thing it represents, cannot be changed and that's why its value is constant in time.
For that you use constant.
A constant is only initialized once, when first encountered during compilation, and never again, so its value remains constant throughout a program run. The compiler can rely on that. So can the reader -- provided they clearly understand what "value" means in this context.1
For example:
BEGIN my $bar = 42;
loop {
constant foo = $bar;
$bar++;
last if $++ > 4;
print foo; # 4242424242
}
Note that if you didn't have the BEGIN then the constant would be initialized and be stuck with a value of (Any).
I tend to leave off the sigil to somewhat reinforce the idea it's a constant but you can use a sigil if you prefer.
Defining a variable bound to another entity with := is also almost clear but not really. If I bind a variable to 3.14, isn't it the same as defining a PI constant? Is $a := $b actually defining $a as an alias to $b or, as some other languages call it, a reference?
Binding just binds the identifiers. If either changes, they both do:
my $a = 42;
my $b := $a;
$a++;
$b++;
say $a, $b; # 4444
Finally, the documentation explains how one can define a sigilless variable (that cannot be varied, so, actually, another kind of constant) but not why one would do that.
It can be varied if the thing bound is a variable. For example:
my $variable = 42; # puts the value 42 INTO $variable
my \variable = $variable; # binds variable to $variable
say ++variable; # 43
my \variable2 = 42; # binds variable2 to 42
say ++variable2; # Cannot resolve caller prefix:<++>(Int:D);
# ... candidates ... require mutable arguments
I personally prefer to slash sigils if an identifier is bound to an immutable basic scalar value (eg 42) or other entirely immutable value (eg a typical List) and use a sigil otherwise. YMMV.
What problems do sigilless variables solve? What's a practical scenario when a variable, a constant, a binding variable do not solve the problem that a sigilless variable solve?
Please add comments if what's already in my answer (or another; I see someone else has posted one) leaves you with remaining questions.
Foonotes
1 See my answer to JJ's SO about use of constant with composite containers.
That's not one but at 5 questions?
If I bind a variable to 3.14, isn't it the same as defining a PI constant?
Well, technically it would be except for the fact that 3.14 is a Rat, and pi (aka π) is a Num.
Is $a := $b actually defining $a as an alias to $b or, as some other languages call it, a reference?
It's an alias.
$number_of_cakes = 4; $also_the_number_of_cakes := $number_of_cakes;
There would be little point. However, sometimes it can be handy to alias something to an element in an array, or a key in a hash, to prevent repeated lookups:
my %foo;
my $bar := %foo<bar>;
++$bar for ^10;
What problems do sigilless variables solve?
Sigilless variables only solve a programming style issue, as far as I know. Some people, for whatever reason, prefer sigilless varriables. It makes it harder to interpolate, but others might find the extra curlies actually a good thing:
my answer := my $ = 42;
say "The answer is {answer}";
What's a practical scenario when a variable, a constant, a binding variable do not solve the problem that a sigilless variable solve?
In my view, sigilless variables do not solve a problem, but rather try to cater different programming styles. So I'm not sure what a correct answer to this question would be.
Also constant is our scoped by default.

Different variable type declaration in Golang

Hi I'm just learning Go since the last view days, read some docs and noted that its something about defining struct or interface. Still cant get the difference between
var result []Struct
and
result := Struct{}
Is there particular docs I can refer to?
The result in the first example is a nil slice. The spec says that variables are initialized to their zero values and that zero value of a slice is nil.
The result in the second example is a Struct value. It uses a short variable declaration and composite literal value for a Struct. The second example identical to
var result Struct
Perhaps you meant to write
result := []Struct{}
for the second example. This is a non-nil zero length slice. The expression []Struct{} is a composite literal for an empty slice of Struct.

Why there are two ways of declaring variables in Go, what's the difference and which to use?

According to the Go reference there are two ways of declaring a variable
Variable_declarations (in the format of var count = 0 or var count int)
and
Short_variable_declarations (in the format of count := 0)
I found it's very confusing to decide which one to use.
The differences I know (till now) are that:
I can only using a count := 0 format when in the scope of a function.
count := 0 can be redeclared in a multi-variable short declaration.
But they do behave the same as far as I know. And in the reference it also says:
It (the count:=0way) is shorthand for a regular variable declaration with initializer expressions but no types
My confusions are:
If one is just the shorthand way of the other, why do they behave differently?
In what concern does the author of Go make two ways of declaring a variable (why are they not merged into one way)? Just to confuse us?
Is there any other aspect that I should keep my eyes open on when using them, in case I fall into a pit?
The Variable declarations make it clear that variables are declared. The var keyword is required, it is short and expresses what is done (at the file level everything excluding comments has to start with a keyword, e.g. package, import, const, type, var, func). Like any other block, variable declarations can be grouped like this:
var (
count int
sum float64
)
You can't do that with Short variable declarations. Also you can use Variable declarations without specifying the initial value in which case each variable will have the zero value of its type. The Short variable declaration does not allow this, you have to specify the initial value.
One of Go's guiding design principle was to make the syntax clean. Many statements require or it is handy that they allow declaring local variables which will be only available in the body of the statement such as for, if, switch etc. To make the syntax cleaner and shorter, Short variable declaration is justified in these cases and it is unambigous what they do.
for idx, value := range array {
// Do something with index and value
}
if num := runtime.NumCPU(); num > 1 {
fmt.Println("Multicore CPU, cores:", num)
}
Another difference: Redeclaration
Quoting from the Language specification:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
This one is also handy. Suppose you want to do proper error handling, you can reuse an err variable because most likely you only need it to check if there were any errors during the last function call:
var name = "myfile.txt"
fi, err := os.Stat(name) // fi and err both first declared
if err != nil {
log.Fatal(err)
}
fmt.Println(name, fi.Size(), "bytes")
data, err := ioutil.ReadFile(name) // data is new but err already exists
// so just a new value is assigned to err
if err != nil {
log.Fatal(err)
}
// Do something with data

Upcasting accesses

Let's say I have a Planet:
type Planet is tagged null record;
type Planet_Ref is access Planet'class;
Now I subclass it:
type Habitable_Planet is new Planet with null record;
type Habitable_Planet_Ref is access Habitable_Planet'class;
Now I define some variables:
p: Planet_Ref := Make_Planet;
hp: Habitable_Planet_Ref := Make_Habitable_Planet;
I would naively expect that assigning p := hp would work, because a Habitable_Planet is a subclass of Planet. But of course that won't work because every type defined with type is distinct and doesn't interoperate with any other type.
So I'd expect to have to declare Habitable_Planet_Ref to be a subtype of Planet_Ref to make this work. But the syntax doesn't seem to allow for this.
How do I make this work?
(Yes, I know I can use an explicit view conversion to cast a Habitable_Planet_Ref to a Planet_Ref, but that's really ugly and I'd like to avoid it.)
Ada recognizes types by name, so indeed you would need a view conversion here.
But if you are using Ada 2005, you can use anonymous access types instead. For instance:
hp: access Habitable_Planet'Class := Make_Habitable_Planet;
p: access Planet'Class := hp; -- valid with anonymous access types
One the drawbacks of using anonymous access types is that the code is more
verbose (although in general you would not use them for local variables, but
as parameters to subprograms or as fields in a (tagged) record.
They also can't be used with Unchecked_Deallocation. In fact, I personally often
use them exactly because of that: when I have a field in a record which is of an
anonymous access type, I know that the record does not "own" the accessed data,
and therefore it should not free it (in fact, I would have to write some convoluted
code to free them).
And of course as per your request the result for type matching are slightly more
relax, which is nice too.
ajb is correct in his comment. Ada is too strict for many practices you might be used to in other languages. An alternative would be to just not use objects and instead just simple records or discriminate records. I understand this may not be what you are looking for, but from my experience more can be done with less lines of code and the solution tends to me easier to understand.
Simple record
--...
type Rec_Planet is record
--.. stuff
end record;
--...
type Rec_Habitable_Planet is record
Planet : Rec_Planet := (others => <>);
--.. stuff
end record;
Discriminate record
type Enum_Planet is (Normal_Planet, Habitable_Planet);
type Rec_Planet(Kind : Enum_Planet := Normal_Planet) is record
-- rec_Planet stuff..
case Kind is
when Habitable_Planet => -- Rec_Habitable_Planet stuff
when others => null;
end case;
end record;
So #manuBriot gave me the answer I needed, but there were some other things I was doing wrong in my question which I should clarify because they'll confuse anyone else reading this question.
I was confusing the issue by using accesses. From Ada's point of view all accesses defined with type are distinct, so it never gets as far as looking at what the access is pointing at; it just disallows the assignment.
However, Ada does support implicit upcasting of class-wide types (and also discrete types, where an instance of a subtype will get implicitly cast to its parent type --- implement ALL the class hierarchies! But that's not really relevant here.) Example here:
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure Prog is
package Superclass is
type Class is tagged record
null;
end record;
procedure Announce(self: in out Class);
subtype Var is Class'class;
end;
package body Superclass is
procedure Announce(self: in out Class)
is
begin
Put_Line("I am the superclass");
end;
end;
package Subclass is
type Class is new Superclass.Class with null record;
procedure Announce(self: in out Class);
end;
package body Subclass is
procedure Announce(self: in out Class)
is
begin
Put_Line("I am the subclass");
end;
end;
osuper: Superclass.Class;
osub: Subclass.Class;
vsuper: Superclass.Var := osuper;
vsub: Superclass.Var := osub; -- implicit upclass here
begin
vsuper.Announce;
vsub.Announce;
end;
(It's in ideone here: http://ideone.com/M79l0a Interesting sidenote. If you define subtype Var is Superclass.Var in the Prog package, and then use Var in the definitions of vsuper and vsub, ideone's Ada compiler crashes.)
Of course, like all indefinite types, once the variable has been initialised then its type cannot be changed. So I can assign any Subclass.Object to vsub, but I can't assign a Superclass.Object to it. And of course I'm physically copying the object rather than referring to an object elsewhere.
Implicitly upcasting accesses to class-wide types should be safe. Because assigning to a class-wide type does a runtime instance check to make sure that the physical type of the objects are compatible, it ought not to be possible to accidentally corrupt objects like you can in C++ --- see Overwriting an instance of a subclass with an instance of a superclass, for example. Therefore assigning to a dereferenced access shouldn't be a problem. However, it's 2100 at night and my brain has turned to sludge, so it's entirely possible that I'm missing something here. (Although given that when using anonymous accesses there aren't any problems, I suspect not.) Elucidation welcome...

Ignore Ada Function Return Values

Is there a way to ignore return values in Ada functions?
I have a function which imports from an Intrinsic.
subtype int32 is Interfaces.Interger_32;
function Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32) return int32;
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
If I want to use this in a procedure, I need to accept the return value or I will get a compiler error:
cannot use function Intrinsic_Sync_Add_And_Fetch in procedure call.
But, if I create a variable that simply takes the return value of the function and is never used then I get compiler warnings. Obviously, I'd rather avoid those.
I can't very well assign the value back to the value I'm adding to; this would undermine the point of the add operation being atomic.
There is the option of taking the value and doing something with it, like:
val := Intrinsic_Sync_Add_And_Fetch(...);
if val := 0 then null; end if;
It forces the code to compile without errors or warnings, but it seems stupid to me. How can I "get around" this language feature and safely ignore the return value?
Edit: What is __sync_add_and_fetch_4?
This is a built-in atomic operation available on Intel CPUs. As such, part of my Autoconf/Automake process would be deciding if the operation is available, and use a fallback implementation, which involves a critical section, if it's not.
You can read about this and similar operations in GCC's section on atomic builtins.
The __sync_add_and_fetch_4 does pretty much exactly what it says. In C, it would look something like this:
int32_t __sync_add_and_fetch_4(int32_t *ptr, int32_t value) {
*ptr += value;
return *ptr;
}
So it's an atomic addition operation, which returns the result of the addition. Basically, it's an atomic += operator. The _4 means that it takes a 4-byte integer.
Edit: I understand that I could probably just switch off that particular compiler warning, but that always feels dirty to me. If there's a solution available that allows me to continue using -Wall -Werror then I'd love to see it.
declare
dummy : constant return_type := my_function;
pragma Unreferenced (dummy);
begin null; end;
or write a wrapper procedure.
If you never want to reference the return value, why not declare the subprogram as a procedure? The value is going to be returned in a register, so throwing it away won’t cause a lot of grief. (I stand to be corrected on this one!)
subtype int32 is Interfaces.Integer_32;
procedure Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32);
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
You said you're only targeting the GNAT compiler. The GNAT User's Guide says:
Note that a special exemption applies to variables which contain any of the substrings DISCARD, DUMMY, IGNORE, JUNK, UNUSED, in any casing. Such variables are considered likely to be intentionally used in a situation where otherwise a warning would be given, so warnings of this kind are always suppressed for such variables.
So the simplest solution to your problem is :
unused := Intrinsic_Sync_Add_And_Fetch(...);
Though you might want to wrap that in a procedure if you are going to use it more than a couple of times :
procedure Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32) is
unused : int32;
begin
unused := Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32);
end Intrinsic_Sync_Add_And_Fetch;
i don't know of any way to ignore the return value of a function in Ada: the language has been especially designed to force you to store those return values.
personally, i would store the return value and ignore any warning regarding the use of the variable. anyway, the said warning is quite strange since the variable is indeed used to store the return value.