Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I Invoke a procedure when inside another procedure in Pascal

procedure questiontype;  
 begin  
  writeln ('Enter the type of question you would like...');  
  writeln ('1. Add');  
  writeln ('2. Multiply');  
  writeln ('3. Subtraction');  
  writeln ('4. Division');  
  readln (typeofquestion);  
   case typeofquestion of
    1: add;
    2: multiply;
    3: subraction;
    4: division   
else writeln ('Choose again'); 
end;
end;          

The add, multiply, subtraction and division are all procedures. If i put this in the main program, it will work fine, but when i make this as a procedure itself, i get the error undeclared identifier. I've looked on many websites for an example that is like this but i can't find any.

How do make add, multiply, subtraction, division go to their procedures from inside this one?

like image 491
captiv Avatar asked Mar 19 '11 16:03

captiv


3 Answers

You have to declare procedures before routines that call them. Although you haven't shown how the other routines are defined, I deduce that they are declared after the routine you have shown.

So you can simply re-order your code so that add, multiply, subtraction and division are defined before they procedure that calls them.

So this will work:

procedure add;
begin
  //do something;
end;

procedure questiontype;  
begin  
  add;  
end;

But this will not compile:

procedure questiontype;  
begin  
  add;  
end;

procedure add;
begin
  //do something;
end;

Pascal and its variants are compiled in a single pass and if the compiler does not know about a routine at the point at which it is mentioned, it cannot continue.

Pascal does support co-routines where A calls B and B calls A, by the use of a *forward declaration`. For example:

procedure B; forward;

procedure A;
begin
  B;
end;

procedure B;
begin
  A;
end;

Naturally this is an infinite loop as written which will terminate with a stack overflow (how appropriate!) but there are of course real examples where this is necessary.

However, forward declarations are rarely needed and should be avoided if possible since they increase complexity. Invariably a solution can be found by simply re-ordering your declarations.

As a final aside, the ordering constraint that declaration occurs before use is explicitly mentioned in Brian Kernighan famous article, Why Pascal is Not My Favorite Programming Language.

like image 110
David Heffernan Avatar answered Nov 15 '22 06:11

David Heffernan


I see you have tagged your question [delphi] as well as [pascal], so I guess you are in fact writing Delphi code. Then you got a few more options, besides caring about the order of the procedures and the forward directive discussed by David.

Most often a Delphi project (GUI or console) is divided into "units". A typical unit looks like this:

unit MyUnit;

interface

const
  RANDOM_NUMBER = 17;

var
  PrintExtraNiceMessage: boolean;

procedure DoThis;
procedure DoThat;

implementation

const
  BUFFER_SIZE = 256;

procedure InitSomething;
begin
  // TODO: do some internal work...
end;

procedure DoThis;
begin
  // TODO: do something
end;

procedure DoThat;
begin
  // TODO: do something else
end;

You will notice that the unit is divided in two parts: the interface part, and the implementation part. The interface part contains only declarations (of functions, procedures, types, constants, and variables); the functions and procedures declared here are defined (that is, implemented) in the implementation section. Notice that there can be functions and procedures defined in the implementation section that have no declarations in the interface section.

The grand idea is that the contents of the interface section is visible to all other units in your program, whereas the contents of the implementation section is only visible inside this very unit. So any other unit in your program can use the RANDOM_NUMBER constant, the PrintExtraNiceMessage variable and the two procedures DoThis and DoThat. But you can only use InitFunction in this very unit (for instance, inside DoThis or DoThat). In addition, the constant BUFFER_SIZE is not visible outside this very unit, either.

This is a very elegant approach. The interface section describes how this unit is used in other units (e.g., what functions there are and how they are used), and the implementation details are "hidden" in the implementation section.

A benefit of this approach is that it solves your problem, at least possibly. If the add, multiply, subtract, and divide procedures should be visible to other units, then they should be declared in the interface section. But then they are indeed known to the compiler by the time it comes to your questiontype procedure, and so you can use call these even if they are defined (implemented) below the questiontype procedure inside the implementation section. But, on the other hand, if it makes no sense at all to let other units use these procedures, then they should not be declared in the interface section, and you need to do as David suggests. This also applies if you have no normal units at all in your project, that is, if you only have the program file, which has no division into interface and implementation parts.

like image 20
Andreas Rejbrand Avatar answered Nov 15 '22 07:11

Andreas Rejbrand


Notice that the OP's example has an else that only applies to the last "if". Presumably, if they enter 1, 2, or 3, the corresponding procedure fires, returns, and then they see 'Choose again'. If they enter 4, they do not. This would be well served by a Case or cascading if..else if structure where the final else is only triggered "when all else fails", which is like what the OP intended.

like image 44
Chris Thornton Avatar answered Nov 15 '22 07:11

Chris Thornton