AdaCore Blog

learn.adacore.com: New Advanced Ada contents

learn.adacore.com: New Advanced Ada contents

by Gustavo A. Hoffmann Guest Author

A while ago, we announced some updates to the learn web­site. In the mean­time, we pub­lished new chap­ters and sec­tions to the Advanced Jour­ney With Ada course, which we dis­cuss today.

New addi­tions #

We added two chap­ters to the Resource Man­age­ment part of the Advanced Jour­ney With Ada course:

More­over, we intro­duced a new chap­ter on record types by mov­ing sec­tions from oth­er chap­ters to this new chap­ter and adding new sec­tions as well.

With these addi­tions, the course’s size increased sub­stan­tial­ly: the PDF ver­sion of the course increased from 651 to 807 pages.

Record Types #

The new chap­ter on record types includes the pre­vi­ous­ly exist­ing sec­tions on mutu­al­ly depen­dent types and null records. In addi­tion, a detailed dis­cus­sion about default ini­tial­iza­tion of record types, record dis­crim­i­nants and per-object expres­sions was added to the chapter.

Lim­it­ed Types #

Lim­it­ed types are types that have the fol­low­ing restric­tions:

We can think of lim­it­ed types as an easy way to avoid inap­pro­pri­ate seman­tics. For exam­ple, a lock should not be copied — nei­ther direct­ly, via assign­ment, nor with pass-by-copy. Sim­i­lar­ly, a file, which is real­ly a file descrip­tor, should not be copied.

In this new chap­ter of the course, we see exam­ples of unwant­ed side-effects that arise if we don’t use lim­it­ed types for these cas­es. In addi­tion, the chap­ter includes more advanced top­ics such as explic­it­ly lim­it­ed types, immutably lim­it­ed types, lim­it­ed types with dis­crim­i­nants, and con­struc­tor func­tions for lim­it­ed types.

Also, when com­pared to non­lim­it­ed types, there are dif­fer­ences when it comes to deriv­ing from lim­it­ed types and using lim­it­ed types as para­me­ters, for exam­ple. The dif­fer­ences in those two areas (and in oth­er areas as well) are explained in details in the chapter.

Con­trolled Types #

Con­trolled types allow us to spec­i­fy the ini­tial­iza­tion and final­iza­tion seman­tics for objects of that type. For any con­trolled object A, an Initialize (A) pro­ce­dure is called right after the object is cre­at­ed, and a Finalize (A) pro­ce­dure is called right before the object is actu­al­ly finalized.

How­ev­er, con­trolled objects aren’t the only way to con­trol the ini­tial­iza­tion of an object. For exam­ple, the lan­guage spec­i­fies that objects of access types are ini­tial­ized by default to null. Like­wise, we can declare types with a default ini­tial val­ue. Sim­i­lar­ly, record types have a very good default ini­tial­iza­tion capa­bil­i­ty for the record com­po­nents. They’re the most com­mon com­ple­tion for pri­vate types, so the facil­i­ty is often used.

Even though these default ini­tial­iza­tion meth­ods pro­vide some con­trol over the objects, they might not be enough in cer­tain sit­u­a­tions. Also, we don’t have any means to per­form use­ful oper­a­tions right before an object goes out of scope. In this case, we can use con­trolled objects to address these limitations.

The choice between using default ini­tial­iza­tion or con­trolled types requires some analy­sis of the spe­cif­ic use-case. Keep in mind that, if only auto­mat­ic ini­tial­iza­tion of an object upon cre­ation is need­ed, then default ini­tial­iza­tion is the first choice, as it’s guar­an­teed and requires noth­ing of the client. In addi­tion, it’s cheap at run-time com­pared to con­trolled types. On the oth­er hand, if oper­a­tions have to be per­formed at the final­iza­tion, then con­trolled types are the best solution.

The new chap­ter starts with an overview of con­trolled types, and then explains each stage of the life­time of a con­trolled object (ini­tial­iza­tion and final­iza­tion), and some pecu­liar­i­ties regard­ing assign­ments and excep­tion han­dling.

Final­ly, appli­ca­tions of con­trolled types are pre­sent­ed in the chap­ter. For exam­ple, we can use con­trolled types to encap­su­late file han­dling, so that files are auto­mat­i­cal­ly cre­at­ed and closed. A com­mon use-case is when a new file is expect­ed to be cre­at­ed or opened when we declare the con­trolled object, and closed when the con­trolled object gets out of scope.

A sim­ple exam­ple is the one of a log­ger, which we can use to write to a log­file by sim­ple calls to Put_Line:

with Ada.Text_IO;      use Ada.Text_IO;
with Ada.Finalization;

package Loggers is

   type Logger (<>) is limited private;

   function Init (Filename : String) return Logger;

   procedure Put_Line (L : Logger; S : String);

private

   type Logger is new Ada.Finalization.Limited_Controlled with
   record
      Logfile : File_Type;
   end record;

   procedure Finalize (L : in out Logger);

end Loggers;

Here, Logger is a lim­it­ed con­trolled type that encap­su­lates a file (stored in the Logfile com­po­nent). The ini­tial­iza­tion of an object of Logger type is enforced by the unknown dis­crim­i­nants, which require a call to Init when the object is declared: this func­tion opens the file descrip­tor and assigns it to the Logfile com­po­nent. The final­iza­tion is han­dled by the Finalize pro­ce­dure, which is called when the object goes out of scope: this pro­ce­dure clos­es the file. Thus, from the user’s per­spec­tive, the log­file is closed auto­mat­i­cal­ly. (You can find more details about this spe­cif­ic exam­ple — includ­ing the com­plete source code — in the chapter.)

Worth men­tion­ing #

The last addi­tion worth men­tion­ing hap­pened in the chap­ter on access types, which was extend­ed with a new sec­tion on mutu­al­ly depen­dent types using access types.

The changel­og page has an overview of the chap­ters and sec­tions that have been added to the course for each release of the learn web­site. More addi­tions are planned for the upcom­ing months, so keep tuned!

Posted in #Learn.adacore.com   

About Gustavo A. Hoffmann

learn.adacore.com coordinator / co-author