Missing operand error in Ada - ada

When compiling this code written in Ada programming language, the next message appears: missing operand in deg:=degree();. Why and how to resolve this issue?
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
With Ada.Strings.Unbounded; Use Ada.Strings.Unbounded;
procedure polynomial is
-- constructs a new polynomial term of the form a * x^b:
function Polynomial(a,b : Integer) return Integer is
type coef is array(Integer range <>)of Integer;
type deg is new Integer;
type c is new Integer;
begin
coef:=new int(b+1);
coef(b):=a;
deg:=degree(); --missing operand
return a;
end Polynomial;

Ada does not accept empty parameter lists. If a function does not accept parameters, omit the parameter list altogether.
deg:=degree;

Related

Printing arrays elements using recursion

I am learning Ada programming language and I can admit that it's strongly typed. In this code, I am trying to ask the user to enter 4 integers and then by using recursion, print out these numbers. However, I am facing trouble writing a recursion subprogram for it and wonder if I can get any suggestions on how to write it correctly?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Dugga is
Y: Natural;
type arr is
array (1..4) of Natural;
A:arr;
function Recurs(Item: in Natural) return Natural is
begin
if Item >= 1 then
return Get(Item ); --Error: Context requires function call, found procedure name
end if;
end Recurs;
begin
Y:=Recurs(arr); --Error: expected type "Standard.Integer. Found type: arr
end Dugga;
Warnings: Program_error may be raised at run time
"return" statement missing following this statement
Error: Missing argument for parameter "Item" in call to get
You appear to be confused about what a recursive subprogram is. A recursive subprogram calls itself unless a termination condition is reached.
If your subprogram calls itself before printing the array element the array elements will be printed in reverse order. If your subprogram calls itself after printing the array element the array elements will be printed in the order they are entered.
with Ada.Text_Io; use Ada.Text_IO;
procedure Main is
subtype Idx is integer range 1..4;
type Arr is array (Idx) of Integer;
procedure Print(Nums : Arr; Index : Idx) is
begin
Put (Nums(Index)'Image);
if Index = Nums'Last then
New_Line;
else
Print(Nums, Index + 1);
end if;
end Print;
A : Arr := (1, 2, 3, 4);
begin
Print(A, A'First);
end Main;
The program above declares an array type and creates an instance of that array type.
The procedure Print is a recursive procedure that prints the value of an array at the specified index value. The procedure then checks the index value. If the index value is the last index value for the array the procedure calls New_Line, otherwise it calls Print with second parameter being Index + 1.
For any recursive algorithm you need to have some sort of control logic (IF, CASE, etc.) that decides between calling the function again with a different input (and returning that result with the potential result of this call) or otherwise returning a final value.
A couple of things.
You say our end game is to use recursion to "print" the values, so your recursive operation only needs to be a procedure. It doesn't need to return anything, it just needs to print something each time it runs. One way to do this is print the first element of the array and then recall the procedure with just the remaining elements. If there are no elements, don't print anything and leave the procedure.
In order to do this, I would recommend passing in the whole array instead of a single value (like your version does). Each time you recursively call the function, you shorten the array until there is no array left. To do this though, you need to adjust your array type to be any potential size, not just 1..4, so that you can use that to end the recursion.
Start with making an array type:
type Natural_Array is array (Positive range <>) of Natural;
Now change the specification of your function to a procedure that uses that type.
procedure Recurse(Numbers: in Natural_Array);
The last part is implementing the recursion:
procedure Recurse(Numbers: in Natural_Array) is
begin
-- See if the array has any elements first
if Numbers'Length > 0 then
-- There are elements in the array, so print the
-- first one. This is why we use Numbers'First
-- as the index
Put_Line(Numbers(Numbers'First)'Image);
-- Now that we printed the first number, lets
-- only pass in the remaining elements in the array
-- here. This is where the "recursion" happens
-- as it calls this function again with a reduced
-- input set. Eventually we'll pass in an
-- empty array once the last element is printed
-- above.
Recurse(Numbers(Numbers'First+1..Numbers'Last));
else
-- Here there weren't any eleemnts in the array
-- left, so lets just end the recursion by
-- doing nothing
null;
end if;
end Recurse;
Here's the full compilable example:
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
type Natural_Array is array (Positive range <>) of Natural;
procedure Recurse(Numbers: in Natural_Array) is
begin
-- See if the array has any elements first
if Numbers'Length > 0 then
-- There are elements in the array, so print the
-- first one. This is why we use Numbers'First
-- as the index
Put_Line(Numbers(Numbers'First)'Image);
-- Now that we printed the first number, lets
-- only pass in the remaining elements in the array
-- here. This is where the "recursion" happens
-- as it calls this function again with a reduced
-- input set. Eventually we'll pass in an
-- empty array once the last element is printed
-- above.
Recurse(Numbers(Numbers'First+1..Numbers'Last));
else
-- Here there weren't any eleemnts in the array
-- left, so lets just end the recursion by
-- doing nothing
null;
end if;
end Recurse;
A : Natural_Array(1..4) := (1,2,3,4);
begin
Recurse(A);
end Hello;

How do I read each word and store it to a variable to use?

I'm new to Ada. Syntax is throws me off. I have 6 years in Java and it's similar to this what we do in java but I quite can't get it working. I'm studying using learn.adacore.com.
with Ada.Text_IO; Use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure TextFile is
F : File_Type;
File_Name : constant String := "Store.txt";
begin
Open (F, In_File, File_Name);
while not End_Of_File (F) loop
Put_Line (Get_Line (F));
end loop;
Close (F);
end TextFile;
This is my text file called Store.txt
Code Department Name/Vendor Title ID Payrate
IL Sales John Sales_person 1378 25.46
If you don't mind portability between different Ada compilers, you can use package GNAT.String_Split to split the whole line as array of separated String values:
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.String_Split; use GNAT.String_Split;
procedure TextFile is
File : File_Type;
Tokens : Slice_Set;
begin
Open (File, In_File, "Store.txt");
-- Skip the file header
Skip_Line (File);
-- Read the data
while not End_Of_File (File) loop
-- Split the line from the file on array which contains separated
-- words. Treat multiple spaces as a single separator (don't
-- create empty elements).
Create (Tokens, Get_Line (File), " ", Multiple);
-- Print each of the array's values
for I in 1 .. Slice_Count (Tokens) loop
Put_Line (Slice (Tokens, I));
end loop;
end loop;
Close (File);
end TextFile;

Ada : put() with custom type

I searching a way to use Put() function with a custom type I create. How could I do this ?
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure main is
type count is range -2..2 ;
begin
Put(counter);
end main;
this is what I got :
Builder results
C:\Users\***********\Desktop\ada project\src\main.adb
26:11 expected type "Standard.Integer"
26:7 no candidate interpretations match the actuals:
26:7 possible missing instantiation of Text_IO.Integer_IO
You're missing the instance, Counter, and there's no subprogram Put that takes a parameter of type Count. Some options:
Option 1 - Use the Image attribute.
with Ada.Text_IO;
procedure Main is
type Count is range -2 .. 2;
Counter : Count := 1;
begin
Ada.Text_IO.Put (Counter'Image); -- Counter'Image returns a String
-- or
Ada.Text_IO.Put (Count'Image (Counter));
end Main;
Option 2 - Cast to type Integer.
with Ada.Integer_Text_IO;
procedure Main is
type Count is range -2 .. 2;
Counter : Count := 1;
begin
Ada.Integer_Text_IO.Put (Integer (Counter));
end Main;
Option 3 - Define a subtype instead of a type.
with Ada.Integer_Text_IO;
procedure Main is
subtype Count is Integer range -2 .. 2;
Counter : Count := 1;
begin
Ada.Integer_Text_IO.Put (Counter);
end Main;
Option 4 - Instantiate generic package Ada.Text_IO.Integer_IO.
with Ada.Text_IO;
procedure Main is
type Count is range -2 .. 2;
Counter : Count := 1;
package Count_Text_IO is
new Ada.Text_IO.Integer_IO (Count);
begin
Count_Text_IO.Put (Counter);
end Main;

How can you store (an access to) Integer's operators in Ada?

In Ada, the context can determine that "+" is not a String but an integer operator, as in the expression: "+"(5,2). The question is, how do I store that operator in a variable? I want to pass that integer operator, or some other one, as a binary function taking two Integers and returning an Integer. In the code below, I made an explicit function that just calls the operator, which I can use as a workaround. Is there some way to avoid having this wrapper, and pass around (an access to) Integer's "+" operator directly?
with Ada.Text_IO; use Ada.Text_IO;
procedure operator is
type binary_int_operator is access function(lhs : Integer; rhs : Integer) return Integer;
--plus : binary_int_operator := Integer."+"'Access;
--plus : binary_int_operator := Integer'Access("+");
--plus : binary_int_operator := Integer'"+";
--plus : binary_int_operator := "+";
function plus(lhs : Integer; rhs : Integer) return Integer is
begin
return lhs + rhs;
end plus;
begin
Put_Line(Integer'Image("+"(5, 12)));
end operator;
The commented declarations show some attempts I made, which do not compile.
I'm afraid you can't do that. The "+" subprogram for Integer is defined in the package Standard [ARM A.1 (17)] and therefore intrinsic [AARM A.1 (2.a)]. It's not allowed to reference an intrinsic subprogram [ARM 3.10.2 (32.3)]. Hence, compiling the program
procedure Main is
type Binary_Int_Operator is
access function (lhs : Integer; rhs : Integer) return Integer;
Plus : Binary_Int_Operator := Standard."+"'Access;
begin
null;
end Main;
yields
6:34 prefix of "Access" attribute cannot be intrinsic
The only workaround is using an indirection. This program compiles
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main_Alt is
type Operation is
access function (Lhs, Rhs : Integer) return Integer;
-- Sticking to "+" and "-" instead of names like Add or Subtract
-- to demonstrate that you can reference operator subprograms
-- (using the Access attribute) as long as they're not intrinsic.
function "+" (Lhs, Rhs : Integer) return Integer is
(Standard."+" (Lhs, Rhs));
function "-" (Lhs, Rhs : Integer) return Integer is
(Standard."-" (Lhs, Rhs));
procedure Calc_And_Show (Lhs, Rhs : Integer; Op : Operation) is
begin
Put (Op (lhs, rhs));
New_Line;
end Calc_And_Show;
begin
Calc_And_Show (5, 3, "+"'Access);
Calc_And_Show (5, 3, "-"'Access);
end Main_Alt;
and yields (as expected)
$ ./main_alt
8
2
I would suggest considering a different approach using generics.
Generally, I think you end up with a simpler interface for the call then you
get trying to pass in access to subprogram parameters.
(i.e. no need to pass the operation for each call).
Using generics, you don't need to use 'Access at all, and you can pass intrinsic functions such as integer "+", as formal generic parameters.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main is
generic
with function Op (L, R : Integer) return Integer;
procedure Calc_And_Show (Lhs, Rhs : Integer);
procedure Calc_And_Show (Lhs, Rhs : Integer) is
begin
Put (Op (lhs, rhs));
New_Line;
end Calc_And_Show;
procedure Calc_And_Show_Plus is new Calc_And_Show (Op => "+");
procedure Calc_And_Show_Minus is new Calc_And_Show (Op => "-");
begin
Calc_And_Show_Plus (5, 3);
Calc_And_Show_Minus (5, 3);
end Main;
There might be reasons why you'd want to use access parameters instead, such as if you wanted Calc_And_Show to be callable from other languages such as C, or if you are in a nested level of code and all you have passed to your nested level is an access to subprogram value. But I think it's generally a good idea to otherwise use generics or at least consider that option as a first preference, unless you have good reason not to.

How to achive PLSQL procedure overloading package

I have a use case where a package has 2 procedure with the same name and argument, one as CHAR type and another is VARCHAR2 type.
How to call tham?
For PL/SQL the package spec and body compiles ok.
But at runtime the 2 procedures are the same and there is no way to distinguish because CHAR type and VARCHAR2 type are of the same datatype family.
For example:
create or replace package pk_over
is
procedure pr_text(p_isbCaracter char);
procedure pr_text(p_isbCaracter varchar2);
End;
create or replace package body pk_over
is
procedure pr_text(p_isbCaracter char)
is
Begin
Dbms_Output.Put_Line('Soy PR_TEXT parĂ¡metro CHAR="'||p_isbCaracter||chr(34));
End pr_text;
--
procedure pr_text(p_isbCaracter varchar2)
is
Begin
Dbms_Output.Put_Line('Soy PR_TEXT parĂ¡metro VARCHAR2="'||p_isbCaracter||chr(34));
End pr_text;
--
End pk_over;
An you call with:
Declare
sbVar2 varchar2(20);
Begin
sbVar2:='Texto 1';
pk_over.pr_text(sbVar2);
End;
The error at runtime is:
PLS-00307: too many declarations of 'PR_TEXT' match this call
So you don't need the 2 procedures, only one.

Resources