Fundamentals of Ada's T'Class - ada

Somewhat embarassed to ask this, but I know it's for the best. I've been programming in Ada for many years now, and understand nearly every part of the language fluently. However, I've never seemed able to wrap my head around T'Class. To borrow from others, can someone "explain it like I'm five?".
Edit: I bought it just to have, but contained within is a great description of, and example use of, T'Class; I refer to “Software Construction and Data Structures with Ada 95” by Michael B. Feldman.

If you start with
package P1 is
type T is tagged private;
procedure Method (Self : T);
end P1;
package P2 is
procedure Proc (Self : T); -- not a primitive
procedure Proc2 (Self : T'Class);
end P2;
In the case of Proc, you are telling the compiler that the parameter should always be considered precisely as of type T (remember that a tagged type is always passed by reference, so the actual type could be derived from T of course, you would not lose the extra data). In particular, that means that within the body of Proc, all calls to Method will be exactly calls to P1.Method, never a call to an overriding Method.
In the case of Proc2, you are telling the compiler that you do not know the exact type statically, so it will need to insert extra code to resolve things at run time. A call to Method, within the body of Proc2, could be call to P1.Method, or to another overriding Method.
Basically: with 'Class, things are resolved at runtime.

Well, if you were five, I would say that T'Class represents the whole family of T.
By family, we mean children and grand-children and grand-grand-children.
As you're not five, it means that this special type represents every tagged type which is in the inheritance tree of T. This way, if you use this type as a parameter, you can use every parameter which has T as ancestor directly or not.
For more information, you can read the wikibooks on this.

Related

Extending a Variable's Lifetime

To be fair, I cannot be entirely sure the title correctly describes the problem I am having, as it merely mirrors my current understanding of Ada as it is.
The Problem
I have a function:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
This function is supposed to create a new menu option for the user, that may in turn be inserted into a menu (one that you might see in a terminal-based environment). You are all probably sighing, as quite evidently, the O variable would be deallocated at the end of this function (from my current understanding). As such, using the Unrestricted_Access here is just plain stupidity, but it mirrors the result of what it is I am trying to accomplish (as this code indeed does compile successfully).
The Access_Option is defined as following:
type Access_Option is access all Option;
The idea is that with an access to the option, which in turn is a discriminated record, is that we can store it within an array-like structure (as the object itself varies in size).
Beyond doubt, it would be nice if we could instead use the Access attribute for this, as the compiler would then make sure the lifetime is long enough of the O variable we are referencing, but as the lifetime as a matter of fact only exists til the end of the Make_Option function, we are presented with the following:
non-local pointer cannot point to local object
What I am then asking, is: how would I go about having a function to create Access_Options for me? Is such a thing even possible, or am I doing it all wrong? To clarify, what I am trying to do is create a neat way for filling an array with references to discriminated records, that I can then dereference and use.
Thought Process
I personally have not tried too many things, more than think about solutions that may be plausible for the problem. And, frankly, rather than going crazy of working makeshift solutions, it would be nice to have a solution that works for large-scale applications too, without messing up the code base to bad.
Would you perhaps have some sort of object queue to handle it? Does Ada even deallocate resources automatically in the first place? Gah. I am confused.
Would it, in fact, be possible to somehow place the O variable outside of the scope for deallocation to then manually deallocate it later?
Given the example you show above a much simpler approach is to simply make an array of Unbounded_String:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
Don't try that.
There are two alternative options:
1) Use Ada.Containers.Indefinite_Vectors instead of a plain array.
2) Give your record discriminant a default value. Then you can store it in a plain array.
You seem to be reinventing the bounded string. Alternatives include
Using an instantiation of Ada.Strings.Bounded.Generic_Bounded_Length
Using Ada.Strings.Unbounded
Using an indefinite container (Ada.Containers.Indefinite_*) to hold type String

Subtypes of Julia concrete types

In order to practising with Julia, I am implementing a little module containing some fixed step ODE solvers (Euler, Runge Kutta, Bulirsch Stoer) using the iterator interface.
My idea was to use multiple dispatch to apply the correct method of the function next to the particular iterator, however the Euler and Runge Kutta iterator type (actually immutable) old the same data.
So I have to choose between:
create two immutable type identical except for the name or
crate a unique immutable with an additional field (say solving_method) and use branching instead of multiple dispatch to address this issue
Both choices seem clunky to me (in particular the second, because the solving_method field is checked at every iteration).
Reading the online discussions about inheritance in Julia I understood that Julia does not have (and will never have) subtypes of concrete types, meaning that one cannot "add fields" to a parent type in this way.
But why I cannot have subtypes of concrete types just for dispatching purposes?
One idiomatic way to solve this flavor of problem is to create a type that stores parameters or the state of the solver and then have a second immutable to specify the method:
type SolverOptions
# ... step size, error tol, etc.
end
immutable RungeKutta end
immutable Euler end
function solve(problem::ODE, method::RungeKutta, options::SolverOptions)
# ... code here ...
end
function solve(problem::ODE, method::Euler, options::SolverOptions)
# ... code here ...
end
Of course, RungeKutta and Euler need not be empty if you want to store some data in there. This isn't always the best solution (and I can't be sure that it will work in your particular case) but it can help when you are trying to prevent duplication of fieldnames.
Maybe try parametric types?
abstract OdeType
abstract Euler <: OdeType
abstract RK4 <: OdeType
immutable Common{T<:OdeType}
x::Int
end

Ada Function Parameter as Access Type or Not

I am refactoring some code originally written using access types, but not yet tested. I found access types to be troublesome in Ada because they can only refer to dynamically allocated items, and referring to items defined at compile time is apparently not allowed. (This is Ada83.)
But now I come to a function like this one:
function Get_Next(stateInfo : State_Info_Access_Type) return integer;
I know that I can easily pass parameter "contents" of an access type rather than the access pointer itself, so I am considering writing this as
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
where State_Info_Type is the type that State_Info_Access_Type refers to.
With this refactor, for all intents and purposes I think I'm still really passing what amounts to an implicit pointer back to the contents (using the .all) syntax).
I want to refactor and test starting with the lowest level functions, working my way up the call chains. My goal is to push the access types out of the code as I go.
Am I understanding this correctly or am I missing something?
I think original author(s), and possibly OP are missing a point, that is, how Ada parameter modes work.
To quote #T.E.D
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Ada does this automatically, and leaves the parameter modes as a way of describing the flow of information (Its NOT the C style reference / value conundrum). See the useful wikibook.
What worries me is that the code you have inherited looks like the author has used the explicit access parameter type as a way of getting functions to have side effects (usually considered a bad thing in Ada - World).
My recommendation is to change your functions to:
function Get_Next(State_Info : in State_Info_Type) return Integer;
and see if the compiler tells you if you are trying to modify State_Info. If so, you may need to change your functions to procedures like this:
procedure Get_Next(State_Info : in out State_Info_Type;
Result : out Integer);
This explicitly shows the flow of information without needing to know the register size or the size of State_Info_Type.
As an aside Ada 2012 Will allow you to have functions that have in out parameters.
To quote #T.E.D,
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Since this code hasn’t yet been tested, I think you are completely right to rework what looks like code written with a C mindset. But, you oughtn’t to mention pointers at all; you suggested
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
but this would be better as
function Get_Next(stateInfo : State_Info_Type) return integer;
or even (IMO) as
function Get_Next(State_Info : State_Info_Type) return Integer;
to use more standard Ada styling! My editor (Emacs, but GPS can do this too) will change state_info into State_Info on the fly.
As an afterthought, you might be able to get rid of State_Info_Type_Pointer altogether. You mention .all, so I guess you’ve got
SITP : State_Info_Type_Pointer := new State_Info_Type;
... set up components
Next := Get_Next (SITP.all);
but what about
SIT : State_Info_Type;
... set up components
Next := Get_Next (SIT);
I wouldn't recommend this, but you can get pointers to variables in Ada 83 by using 'Address.
You can then use overlays (again this is all Ada83 stuff) to achieve access...
function something(int_address : Address) return integer
is
x : integer;
for x'address use int_address;
begin
-- play with x as you will.

Invoking a primitive operation via dot operator fails

I have a problem understanding how the UFCS (Universal Function Call Syntax) works in Ada.
Let's say I have a type, like:
package People
type Person is tagged private;
-- This procedure is a primitive operation:
procedure Say_Name (Person_Object : in Person);
private
type Person is tagged record
Name : String;
end record;
end People;
then I can call the procedure as if it actually belonged to the Person type:
Some_Person_Instance.Say_Name;
Now that works, but in my particular instance it doesn't make sense to have a record, and a subtype would suffice.
subtype Person is String;
At this point (assuming I changed the procedure's workings), it fails to compile and I get the error:
invalid prefix in selected component "Person".
Why? It doesn't even help if I do:
type Person is new String;
Does UFCS only work for records?
I apologize if this is an inane question, but I've no study materials for Ada (apart for couple of e-books) and the textbook I ordered hasn't arrived yet.
UFCS is a full feature of the D language. For historical reasons, Ada has mixed approaches to calls in different parts of the language.
Ordinary subprogram calls are dealt with in ARM 6.4, and look like Subprogram_Name (Parameters) (or just Subprogram_Name if there are no parameters).
Protected subprogram calls (ARM 9.5.1) and entry calls (ARM 9.5.3) look like Object.Subprogram_Or_Entry_Name (Parameters).
Primitive subprograms of tagged types, however, can be called either way; either as an ordinary call, or, if the tagged parameter is the first parameter, using the prefix notation (ARM 4.1.3(9.1)).
There is discussion of this design in AI95-00252; apparently the designers did consider allowing both call forms for all types, but there were too many complications and too few benefits. A shame, I think we all agree, though perhaps it can be taken too far; the D example (from here)
values.multiply(10).divide(3).evens.writeln;
might be a case in point!
With regard to learning Ada and Web resources, have a look at the Ada Resource Association’s resource list.

OCaml visitor pattern

I am implementing a simple C-like language in OCaml and, as usual, AST is my intermediate code representation. As I will be doing quite some traversals on the tree, I wanted to implement
a visitor pattern to ease the pain. My AST currently follows the semantics of the language:
type expr = Plus of string*expr*expr | Int of int | ...
type command = While of boolexpr*block | Assign of ...
type block = Commands of command list
...
The problem is now that nodes in a tree are of different type. Ideally, I would pass to the
visiting procedure a single function handling a node; the procedure would switch on type of the node and do the work accordingly. Now, I have to pass a function for each node type, which does not seem like a best solution.
It seems to me that I can (1) really go with this approach or (2) have just a single type above. What is the usual way to approach this? Maybe use OO?
Nobody uses the visitor pattern in functional languages -- and that's a good thing. With pattern matching, you can fortunately implement the same logic much more easily and directly just using (mutually) recursive functions.
For example, assume you wanted to write a simple interpreter for your AST:
let rec run_expr = function
| Plus(_, e1, e2) -> run_expr e1 + run_expr e2
| Int(i) -> i
| ...
and run_command = function
| While(e, b) as c -> if run_expr e <> 0 then (run_block b; run_command c)
| Assign ...
and run_block = function
| Commands(cs) = List.iter run_command cs
The visitor pattern will typically only complicate this, especially when the result types are heterogeneous, like here.
It is indeed possible to define a class with one visiting method per type of the AST (which by default does nothing) and have your visiting functions taking an instance of this class as a parameter. In fact, such a mechanism is used in the OCaml world, albeit not that often.
In particular, the CIL library has a visitor class
(see https://github.com/kerneis/cil/blob/develop/src/cil.mli#L1816 for the interface). Note that CIL's visitors are inherently imperative (transformations are done in place). It is however perfectly possible to define visitors that maps an AST into another one, such as in Frama-C, which is based on CIL and offer in-place and copy visitor. Finally Cαml, an AST generator meant to easily take care of bound variables, generate map and fold visitors together with the datatypes.
If you have to write many different recursive operations over a set of mutually recursive datatypes (such as an AST) then you can use open recursion (in the form of classes) to encode the traversal and save yourself some boiler plate.
There is an example of such a visitor class in Real World OCaml.
The Visitor pattern (and all pattern related to reusable software) has to do with reusability in an inclusion polymorphism context (subtypes and inheritance).
Composite explains a solution in which you can add a new subtype to an existing one without modifying the latter one code.
Visitor explains a solution in which you can add a new function to an existing type (and to all of its subtypes) without modifying the type code.
These solutions belong to object-oriented programming and require message sending (method invocation) with dynamic binding.
You can do this in Ocaml is you use the "O" (the Object layer), with some limitation coming with the advantage of having strong typing.
In OCaml Having a set of related types, deciding whether you will use a class hierarchy and message sending or, as suggested by andreas, a concrete (algebraic) type together with pattern matching and simple function call, is a hard question.
Concrete types are not equivalent. If you choose the latter, you will be unable to define a new node in your AST after your node type will be defined and compiled. Once said that a A is either a A1 or a A2, your cannot say later on that there are also some A3, without modifying the source code.
In your case, if you want to implement a visitor, replace your EXPR concrete type by a class and its subclasses and your functions by methods (which are also functions by the way). Dynamic binding will then do the job.

Resources