I've got a simple package in Ada with procedures and functions. I'd like to have all the functions and procedures in a protected type.
e.g. for a simple .adb file
package body Pack is
procedure procedure1 (B : in out Integer) is
begin
B := new Integer;
end procedure1;
procedure procedure2 (B: in out Integer) is
begin
B.Cont(B.First-1) := 1;
end procedure2;
function procedure3 (B : Integer) return Boolean is
begin
return B.First = B.Last;
end procedure3;
end pack;
and or a simple .ads
package body Pack is
procedure procedure1 (B : in out Integer);
procedure procedure2 (B: in out Integer);
function procedure3 (B : Integer) return Boolean;
end pack;
How would I go about it?
The thing about a protected type is that it protects something (against concurrent access). It’s hard to see from your code what it is you want to protect.
If, say, you wanted to do a thread-safe increment, you might have a spec like
package Pack is
protected type T is
procedure Set (To : Integer);
procedure Increment (By : Integer);
function Get return Integer;
private
Value : Integer := 0;
end T;
end Pack;
(this is far from perfect; you’d like to be able to specify the initial Value when you declare a T, but that’s starting to get complicated).
In this case, the thing to be protected is the Value. You want to be sure that if two tasks call Increment at the “same” time, one with By => 3 and one with By => 4, the Value ends up being incremented by 7.
The body could look like
package body Pack is
protected body T is
procedure Set (To : Integer) is
begin
Value := To;
end Set;
procedure Increment (By : Integer) is
begin
Value := Value + By;
end Increment;
function Get return Integer is
begin
return Value;
end Get;
end T;
end Pack;
Recommended reading: the Wikibooks section on protected types.
Related
My code is under , i will be gratefull for any suggestion
(* //const
//pi=3.1415926;
//uses
//mathh.inc; *)
var
r,pole_kola,obwod_kola: real;
function Pi: valreal;
begin
Pi:=3.1415926;
end;
procedure dane();
begin
read(r);
end;
procedure obliczenia();
begin
pole_kola:= {pi}Pi*r*r;
obwod_kola:= 2*{pi}Pi*r;
end;
procedure wyniki();
begin
writeln('pole koła: ',pole_kola:4:8);
writeln('obwód koła: ',obwod_kola:4:8);
end;
begin
writeln('podaj promien r: ');
dane();
obliczenia();
wyniki();
end.
How i can use function Pi :
https://www.freepascal.org/docs-html/rtl/system/pi.html
to return automatic value of "PI" from function without assign in operation part of function body if i try modify function get back
Function result does not seem to be set
function Pi() :valreal;
begin
end;
begin
WriteLn('pi = ', Pi():1:20);
end.
Compiling main.pas
main.pas(1,10) Warning: Function result does not seem to be set
Linking a.out
8 lines compiled, 0.1 sec
1 warning(s) issued
pi = 0.00000000000000000000
in program
./main
podaj promien r:
6
pole koła: 0.00000000
obwód koła: 0.00000000
In the task, I wanted to automatically use a ready value for PI (3.14…) without using my function. My function didn’t returned a value because I didn’t assigned one. Like we see here:
function Pi() :valreal;
begin
//here is nothing but must be returned a value
end;
begin
WriteLn('pi = ', Pi():1:20);
end.
Going by #derpirscher’s comment, the function written by hand always needs to return something. So I commented part of my syntax, and used the built-in function named PI. (Pascal includes that function.)
(* function pi: valreal; // If I define my own function, it must return a value
begin
pi:=3.1415926; // So in the body of the function, we must assign value
end; *)
We see that here
procedure obliczenia();
begin
pole_kola:= {pi}Pi*r*r; // using build in function
obwod_kola:= 2*{pi}Pi*r; // as above
end;
If we need to use the value of PI in our task/homework, we can use predefinied built-in functions because it is easier; it is good practice to use less syntax in our code.
Must remember: If we define a function i.e., named Pi ourselves, it has to return a value.
Under the comment, the entire syntax of my code with corrections:
var
r,pole_kola,obwod_kola: real;
(* function pi: valreal; // If I define my own function, it must return a value
begin
pi:=3.1415926; // So in the body of the function, we must assign value
end; *)
procedure dane();
begin
read(r);
end;
procedure obliczenia();
begin
pole_kola:= {pi}Pi*r*r; // using build in function
obwod_kola:= 2*{pi}Pi*r; // as above
end;
procedure wyniki();
begin
writeln('pole koła: ',pole_kola:4:8);
writeln('obwód koła: ',obwod_kola:4:8);
end;
begin
writeln('podaj promien r: ');
dane();
obliczenia();
wyniki();
end.
Consider the following:
with Ada.Containers.Hashed_Maps;
with Ada.Containers; use Ada.Containers;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
package Tiles is
-- Implementation is completely hidden
type Tile_Type is private;
type Tile_Set is tagged private;
type Tile_Key is private;
procedure Add (Collection : in out Tile_Set; Tile : Tile_Type);
function Get (Collection : in Tile_Set; Key : Natural) return Tile_Type;
function Make (Key : Natural; Data : Integer) return Tile_Type;
function Image (Tile : Tile_Type) return String;
private
type Tile_Key is record
X : Natural;
end record;
function Tile_Hash (K : Tile_Key) return Hash_Type is
(Hash_Type (K.X));
type Tile_Type is record
Key : Tile_Key;
Data : Integer;
end record;
package Tile_Matrix is new Ada.Containers.Hashed_Maps
(Element_Type => Tile_Type,
Key_Type => Tile_Key,
Hash => Tile_Hash,
Equivalent_Keys => "=");
use Tile_Matrix;
type Tile_Set is new Tile_Matrix.Map with null record;
end Tiles;
package body Tiles is
procedure Add (Collection : in out Tile_Set; Tile : Tile_Type) is
begin
Collection.Include (Key => Tile.Key, New_Item => Tile);
end Add;
function Get (Collection : in Tile_Set; Key : Natural) return Tile_Type is
K : Tile_Key := (X => Key);
C : Cursor := Collection.Find (Key => K);
begin -- For illustration, would need to handle missing keys
return Result : Tile_Type do
Result := Collection (C);
end return;
end Get;
function Image (Tile : Tile_Type) return String is
(Tile.Key.X'Image & '=' & Tile.Data'Image);
function Make (Key : Natural; Data : Integer) return Tile_Type is
New_Key : Tile_Key := (X => Key);
begin
return Result : Tile_Type do
Result.Key := New_Key;
Result.Data := Data;
end return;
end Make;
end Tiles;
use Tiles;
S : Tile_Set;
T : Tile_Type;
begin
S.Add (Make (Key => 1, Data => 10));
T := S.Get (1);
Put_Line (Image (T)); -- 1, 10
S.Add (Make (Key => 2, Data => 20));
T := S.Get (2);
Put_Line (Image (T)); -- 1, 20
for X in S loop -- Fails: cannot iterate over "Tile_Set"
-- +: to iterate directly over the elements of a container, write "of S"
-- but "for X of S" doesn't work either.
T := S (X); -- Fails: array type required in indexed component
-- presumably because X isn't a cursor?
Put_Line (Image (T));
end loop;
end;
It seems to me that the compiler has enough knowledge to iterate over a Tile_Set and I'm supposing it won't because I haven't exposed an iterator.
How should I modify this so that 'for X is S loop' is valid?
More generally, what is the idiom for hiding the implementation of underlying containers, whilst exposing indexing, iterating etc.?
It seems to me that the compiler has enough knowledge to iterate over a Tile_Set and I'm supposing it won't because I haven't exposed an iterator.
That assessment is correct. To be able to loop over a type, the type needs to define the aspects Default_Iterator and Iterator_Element, as described in LRM 5.5.1, and the aspect Constant_Indexing as described in LRM 4.1.6. Both sections read
These aspects are inherited by descendants of type T (including T'Class).
This means that since Tile_Set inherits from Tile_Matrix.Map, it does inherit these aspects which are defined on that map. However, since the inheritance relation is private, the aspects are not visible outside of that package.
You also cannot set them for the private type explicitly since 4.1.6 says
The aspects shall not be overridden, but the functions they denote may be.
Setting them on the private type would override the aspects inherited in the private part.
That leaves you with two options:
Make the inheritance relation public so that you get immediate access to all of the aspects.
Make Tile_Set encapsulate the Hashed_Map value, so that you can implement your own iteration on the type.
The second option would look like this:
type Cursor is private;
type Tile_Set is private
with Default_Iterator => Iterate,
Iterator_Element => Tile_Type,
Constant_Indexing => Constant_Reference;
function Has_Element (Position: Cursor) return Boolean;
package Tile_Set_Iterator_Interfaces is new
Ada.Iterator_Interfaces (Cursor, Has_Element);
type Constant_Reference_Type
(Element : not null access constant Tile_Type) is private
with Implicit_Dereference => Element;
function Iterate (Container: in Tile_Set) return
Tile_Set_Iterator_Interfaces.Forward_Iterator'Class;
function Constant_Reference (Container : aliased in Tile_Set;
Position : Cursor)
return Constant_Reference_Type;
private
-- ..
type Cursor is record
Data : Tile_Matrix.Cursor;
end record;
type Tile_Set is record
Data : Tile_Matrix.Map;
end record;
In the implementation of these subroutines, you can simply delegate to the Tile_Matrix subroutines.
The lesson is that you shouldn't inherit when your actual intent is composition.
Is it possible, that a function can return a function in Ada? I am trying to get currying to work.
type Integer_Func_Type is access function (Y : Integer) return Integer;
function Add (X : Integer) return Integer_Func_Type is
function Inner (Y : Integer) return Integer is
begin
return X + Y;
end Inner;
begin
return Inner'Access;
end;
At the end, I do not want to provide all arguments of a function one at a time. For example: if x is a ternary function and y is curry(x), then I can use following function calls: y(a,b,c), y(a,b)(c), y(a)(b,c), y(a)(b)(c).
EDIT
I implemented 'Jacob Sparre Andersen' suggestions. But it does not look like currying will be easy to implement. I must implement every possible variant of any type I want to use in advance. Is this correct?
with Ada.Text_IO;
with R;
procedure Hello is
Add_Two : R.Test2 := (X => 2);
begin
Ada.Text_IO.Put_Line(Add_Two.Add(3)'Img);
end Hello;
r.adb
package body R is
function Add(A : Test2; Y : Integer) return Integer is
begin
return A.X + Y;
end Add;
end R;
r.ads
package R is
type Test is abstract tagged null record;
function Add(A : Test; Y : Integer) return Integer is abstract;
type Test2 is new Test with
record
X : Integer;
end record;
overriding
function Add(A : Test2; Y : Integer) return Integer;
end R;
This is how to do it with generics:
with Ada.Text_IO;
procedure Test is
-- shorthand Ada 2012 syntax; can also use full body
function Add (X, Y : Integer) return Integer is (X + Y);
generic
type A_Type (<>) is limited private;
type B_Type (<>) is limited private;
type Return_Type (<>) is limited private;
with function Orig (A : A_Type; B : B_Type) return Return_Type;
A : A_Type;
function Curry_2_to_1 (B : B_Type) return Return_Type;
function Curry_2_to_1 (B : B_Type) return Return_Type is
(Orig (A, B));
function Curried_Add is new Curry_2_to_1
(Integer, Integer, Integer, Add, 3);
begin
Ada.Text_IO.Put_Line (Integer'Image (Curried_Add (39)));
end Test;
As you see, it is quite verbose. Also, you need to provide a currying implementation for every count X of parameters of the original function and every number Y of parameters of the generated function, so you'd have a lot of Curry_X_to_Y functions. This is necessary because Ada does not have variadic generics.
A lot of the verbosity also comes from Ada not doing type inference: You need to explicitly specifiy A_Type, B_Type and Return_Type even though theoretically, they could be inferred from the given original function (this is what some functional programming languages do).
Finally, you need a named instance from the currying function because Ada does not support anonymous instances of generic functions.
So, in principle, currying does work, but it is not anything as elegant as in a language like Haskell. If you only want currying for a specific type, the code gets significantly shorter, but you also lose flexibility.
You can't do quite what you're trying to do, since Inner stops to exist as soon as Add returns.
You could do something with the effect you describe using tagged types.
One abstract tagged type with a primitive operation matching your function type.
And then a derived tagged type with X as an attribute and an implementation of the function matching Inner.
Many of the answers seem to deal with ways to have subprograms that deal with variable numbers of parameters. One way to deal with this is with a sequence of values. For example,
type Integer_List is array (Positive range <>) of Integer;
function Add (List : Integer_List) return Integer;
can be considered a function that takes an arbitrary number of parameters of type Integer. This is simple if all your parameters have the same type. It's more complicated, but still possible, if you deal with a finite set of possible parameter types:
type Number_ID is (Int, Flt, Dur);
type Number (ID : Number_ID) is record
case ID is
when Int =>
Int_Value : Integer;
when Flt =>
Flt_Value : Float;
when Dur =>
Dur_Value : Duration;
end case;
end record;
type Number_List is array (Positive range <>) of Number;
function Add (List : Number_List) return Number;
If you have to be able to handle types not known in advance, this technique is not suitable.
I'm writing long digit arythmetics. This is a function for adding to longint long binary digits. I need to output the sum inside the function, to debug it. How could I do it, without creating new variables?
function add(var s1,s2:bindata;shift:longint):bindata;
var l,i:longint;
o:boolean;
begin
writeln(s1.len,' - ',s2.len);
o:=false;
l:=max(s1.len,s2.len);
add.len:=0;
for i:=1 to l do begin
if o then Begin
if s1.data[i+shift] then Begin
if (s2.data[i]) then add.data[i+shift]:=true
Else add.data[i+shift]:=false;
End
else if s2.data[i] then add.data[i+shift]:=false
else Begin
add.data[i+shift]:=true;
o:=false;
End;
End
Else Begin
if s1.data[i+shift] then Begin
if s2.data[i] then
Begin
add.data[i+shift]:=false;
o:=true;
End
Else add.data[i+shift]:=true;
End
else if s2.data[i] then add.data[i+shift]:=true
else add.data[i+shift]:=false;
End;
output(add); //Can I output a variable?
end;
add.len:=l;
if o then Begin
inc(add.len);
add.data[add.len]:=true;
End;
end;
You are accumulating the result of the function within the function result variable, which is generally fine, but uses an outdated style, and leads to exactly the problem you're facing here. You're trying to report an intermediate value of the function result, and to do that, you're trying to reference the name of the function, add. When you do that, though, the compiler interprets it as an attempt to report the function itself, rather than the expected return value of this particular invocation of the function. You'll get the address of the function, if output is defined to accept function addresses; otherwise, you'll get a compiler error.
If your compiler offers a certain common language extension, then you should use the implicit Result variable to refer to the intermediate return value instead of continuing to refer to it by the function name. Since Result is declared implicitly, you wouldn't have to create any other variables. The compiler automatically recognizes Result and uses it as an alias for the function's return value. Simply find every place you write add within the function and replace it with Result. For example:
if o then begin
Inc(Result.len);
Result.data[Result.len] := True;
end;
Turbo Pascal, Free Pascal, GNU Pascal, and Delphi all support the implicit Result variable, but if you've managed to get stuck with a compiler that doesn't offer that extension, then you have no choice but to declare another variable. You could name it Result, and then implement your function with one additional line at the end, like so:
function add(var s1, s2: bindata; shift: longint): bindata;
var
l, i: longint;
o: boolean;
Result: bindata;
begin
{
Previous function body goes here, but with
`add` replaced by `Result`
}
{ Finally, append this line to copy Result into the
function's return value immediately before returning. }
add := Result;
end;
How can I retrieve the return value of a stored procedure using iBatis.NET? The below code successfully calls the stored procedure, but the QueryForObject<int> call returns 0.
SqlMap
<procedure id="MyProc" parameterMap="MyProcParameters" resultClass="int">
MyProc
</procedure>
<parameterMap id="MyProcParameters">
<parameter property="num"/>
</parameterMap>
C# code
public int RunMyProc( string num )
{
return QueryForObject < int > ( "MyProc", new Hashtable { { "num", num } } );
}
Stored Procedure
create procedure MyProc
#num nvarchar(512)
as
begin
return convert(int, #num)
end
FYI, I'm using iBatis 1.6.1.0, .NET 3.5, and SQL Server 2008.
It's not pretty, but this works:
SqlMap
<statement id="MyProc" parameterClass="string" resultClass="int">
declare #num int
exec #num = MyProc #value#
select #num
</statement>
C# code
public int RunMyProc( string num )
{
return QueryForObject < int > ( "MyProc", num );
}
You might want to check out the following article
http://www.barebonescoder.com/2010/04/ibatis-net-stored-procedures-return-values/ on how to retrieve return values.
I've used it in QueryForObject and Insert scenarios where the last statement is a return statement in the stored procedure.
Pay particular attention to the class attribute on the "parameterMap" element. It's a lot prettier than the answer above and I believe it's more inline with the way IBatis.Net was intended to be used.
Stored procedures don't have a return value like functions.
So, I don't think that will work. Try using output parameters instead.
I'm not sure about your application logic, but your procedure would be better like this:
create procedure MyProc
#num nvarchar(512)
as
begin
DECLARE #ReturnValue int
BEGIN TRY
SET #ReturnValue=convert(int, #num)
END TRY
BEGIN CATCH
SET #ReturnValue=0 --procedures can not return null, so set some default here
END CATCH
return #ReturnValue
end