Although setting default values for data fields when initializing a record
is supported by Ada
at the syntax level of the language. However, in the previous article about the record
, I avoided mentioning it to keep the record
definition simple and focus on the data type elements. And now is the right time for us to learn more about record
in Ada
.
Record Defaults
To set default values for the data fields of the record
, the operation that needs to be done is simply appending an assignment after the data type elements similar to languages like TypeScript
or Kotlin
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | with Ada.Text_IO; use Ada.Text_IO; procedure Main is type Date is record Day : Integer range 1 .. 31 := 1; Month : Integer range 1 .. 12 := 1; Year : Integer range 1 .. 3000 := 1900; end record; Birthday : Date; begin Put_Line ("Birthday : record Date"); Put_Line (" Day => " & Integer'Image (Birthday.Day)); Put_Line (" Month => " & Integer'Image (Birthday.Month)); Put_Line (" Year => " & Integer'Image (Birthday.Year)); end Main; |
And in fact, all variables declared anywhere, including parameters of sub-program
and local variables can be defaulted with the same operation (if necessary, needs).
1 2 3 4 5 | Birthday : record Date Day => 1 Month => 1 Year => 1900 |
Discriminant
record
can also be defined with discriminant
. This is also necessary if we are designing a record
that contains array
and want to let the outside code decide the width of the array
inside the record
at the time of data type for the storage variable.
1 2 3 4 5 6 | subtype Positive_Integer is Integer range 1 .. Integer'Last; type Item_List (size : Positive_Integer) is record Name : String; List : array (1 .. size) of String; end record; |
In addition, discriminant
elements are also used to define variant record
– roughly understood as the type of record
whose structure changes depending on the discriminiant
element provided at the time of styling a certain variable. Ada
‘s variant record
are compared to union
in C
or C++
and sum type
in FP
languages like Elm
or Haskell
.
However, for some syntactical reasons, I will not use variant record
throughout this Sub-Series and will only quote the reference link here if you are interested in learn.adacore.com > Variant Records
.
Access Pointers
pointer
variables in C
or C++
are very powerful programming tools. However, from the perspective of the application environment and Ada
‘s design philosophy, these are unsafe structures. That’s why Ada
provided alternative tools such as in
and out
instructions for parameters of sub-program
, and a reference variable concept called access
.
Although called a pointer type by Ada
, access
variables do not have the same structural meaning as pointer
in C
or C++
, but in fact access
pointers are only nominal in nature and provide an additional syntax used instead of the original data type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | with Ada.Text_IO; use Ada.Text_IO; procedure Main is type Item; -- early declaration type Item_Access is access Item; -- detail definition type Item is record Value: Integer; Next_Access: Item_Access; end record; -- declare a list Integer_List_Access: Item_Access; -- declare a cursor Current_Access: Item_Access; begin Integer_List_Access := new Item'( Value => 0, Next_Access => null ); Current_Access := Integer_List_Access; -- add new item Current_Access.Next_Access := new Item'( Value => 1, Next_Access => null ); Current_Access := Current_Access.Next_Access; -- add new item Current_Access.Next_Access := new Item'( Value => 2, Next_Access => null ); Current_Access := Current_Access.Next_Access; -- move cursor to first item and print list Current_Access := Integer_List_Access; loop Put_Line ( "Item Value : " & Integer'Image (Current_Access.Value)); exit when Current_Access.Next_Access = null; Current_Access := Current_Access.Next_Access; end loop; end Main; |
1 2 3 4 | Item Value : 0 Item Value : 1 Item Value : 2 |
In this example code we are defining Integer_List
as a list that goes from one Item
to Item
next, and so on until infinity. We will not be able to define a Next
field that points to the Item
type itself, but we can create an indirect access
pointer type to Item
to use here.
All operations performed through access
pointers have the same syntax as normal variables, except that initialization of the stored value will require the use of the new
implementation. At this point, the initialization value will be attached to the type name by the '
symbol like a Type'Attribute
that we knew earlier. Example: new String'("value")
And here we have a null
value that Ada
only uses for access
pointers to describe the indeterminate state, not yet pointing to a data object. Also, as mentioned earlier, Ada
does not support the use of null
values for other data types. When building package
that provide tools to work with a certain data type, we will have to define the meaningless value case ourselves with the operation logic of the sub-program
if necessary.
Oh, and we know again that data types can be declared with a brief declaration
at the top and then a detailed definition
can be written at a later time. This way we will be able to use the name of a declared data type temporarily for other related data type definitions – before writing a concrete definition for the original type.
There is still a lot to talk about about record
and we will continue to learn more in the next articles.