In the opening chapterroutines were already mentioned.Routines are, as it was described before, reusable pieces of code that can be used over and over again.Examples of routines areread / readLn andwrite / writeLn.You can invoke,call, these routines as many times as you want.In this chapter you will learn
Routines come in two flavors.In Pascal, routines can either replace statements, or they replace a (sub‑)expression.A routine that can be used where statements are allowed is called aprocedure.A routine that is called as part of an expression is afunction.
Afunction is a routine that returns a value.Pascal defines, among others, a functionodd.The functionodd takes oneinteger-expression as a parameter and returnsfalse ortrue, depending on the parity of the supplied parameter (in layman terms that means whether it is divisible by 2).Let’s see the functionodd in action:
programfunctionDemo(input,output);varx:integer;beginwrite('Enter an integer: ');readLn(x);ifodd(x)thenbeginwriteLn('Now this is an odd number.');endelsebeginwriteLn('Boring!');end;end.
Odd(x) is pronounced“odd of x”.First, the expression in parentheses is evaluated.Here it is simplyx, the variable’s value to be precise, but a more complex expression is allowed too, as long as it eventually evaluates to aninteger-expression.Thevalue of this expression, theactual parameter, is then handed to a (in this case invisible) block of code that processes the input, performs some calculations on it, andreturnsfalse ortrue according to the calculation’s findings.The function’s returned value is ultimately filled in in place of the function call.You can, in your mind, readfalse / true in place ofodd(x), although this is dynamic depending on the given input.
You are only allowed to call functions where you can put an expression. The following program is wrong: programlostFunction;beginodd(42);end. false. Butfalse is not a statement. You can only putstatements betweenbegin andend, no expressions.[fn 1] |
Procedures on the other hand cannot be used as part of an expression.You can only call procedures where statements are allowed.
A routine can either be a function or a procedure. In some programming languages the routine used to retrieve data from the console can be used like a function, but this is not the case in Pascal. The following program will not compile:programstrayProcedure(input,output);beginifreadLn(input)=''thenbeginwriteLn('Error: No input supplied.');end;end. ReadLn refers to aprocedure thus it does not return anything, yet at this specific position a value has to be inserted so theif‑branch language construct and the equal comparison make sense. |
Aprocedure may use functions, and the other way around.Do not understand afunction as a mere substitute for an expression.In the following section we will learn why.
The dichotomy of routines, distinguishing between aprocedure and afunction, is meant to gently push the programmer to write “clean” programs.Doing so, a routine does not conceal whether it is just a replacement for a sequence of statements or shorthand for a complex, difficult to write out expression.This kind of notation works without introducing nasty pseudo types like, for example,void in the C programming language where every routine is a function, but the “invalid” data typevoid will allow you to make it (in part) behave like aprocedure.
Defining routines follows a pattern you are already familiar with since your very firstprogram.Aprogram is, in some regards, like aspecial routine:You can run it as many times as you want throughOS-defined means.Aprogram’s definition looks almost just like a routine’s.
A routine is defined by,
in that order.The routine header shows a couple differences depending on whether it is afunction orprocedure.We will first take a look at blocks, since these are the same for both types of routines.
Ablock is the synthesis of a productive part (statements) and (optional) declarations and definitions.In Standard Pascal (as laid out by theISO standard 7185) a block has a fixed order:[fn 2]
const-section)type-section)var-section)begin…end, possibly empty)All items but the last one, the productive part, are optional.
Sections (const,type, orvar-section) may not be empty. Once you specify a section heading, you have to define/declare at least one symbol in the just started section. |
InEP, the fixed order restriction has been lifted.There, sections and routine declarations and definitions may occur as many times as needed and do not necessarily have to adhere to a particular order.The consequences are detailed in thechapter “Scopes”.For the remainder of this book we will refer toEP’s definition ofblock, because all major compilers support this.Nevertheless, the order defined by Standard Pascal is a good guideline:It makes sense to define types, before there is a section that may use those types (i. e.var-section).
A routine header consists of
function orprocedure,The parameter list for routines also defines the data type of every single parameter.Thus, the header of the functionodd could look like this:
functionodd(x:integer):Boolean;
Take notice of the colon (:) after the parameter list separating the function’s result data type.You can view functions as sort of special variable declaration which also separates an identifier with a colon, except in the case of a function the “variable’s” value is computed dynamically.
Formal parameters, i. e. parameters in the context of a routine header, are separated by a semicolon.Consider the following procedure header:
procedureprintAligned(x:integer;tabstop:integer);
Note that every routine header is terminated with a semicolon.
While the routine header tells the processor (usually a compiler), “Hey, there’s a routine with the following properties: […]”, it is not enough.You have to “flesh out”, give the routine abody.This is done in the subsequent block.
Inside the block all parameters can be read as if they were variables.
In the sequence of the block defining a function there is automatically a variable of the function’s name.You have to assign a value exactly one time, so the function, mathematically speaking, becomes defined.Confer this example:
functiongetRandomNumber():integer;begin// chosen by fair dice roll,// guaranteed to be randomgetRandomNumber:=4;end;
Note that the block did not contain avar-section declaring the variablegetRandomNumber, but it is already implicitly declared by the function’s header:Both the name and the data type are part of the function header.
A routine declaration happens most of the time implicitly.Declaring a routine, or in general any identifier, refers to the process of giving the processor (i. e. usually a compiler) information in order to correctly interpret your program source code.This information is not directly encoded in your executable program, but it is implicitly there.Examples are:
type declarations merely serve the purpose of clean and abstract programming, but those declarations do not end up in the executable program file.[fn 4]Declarations make an identifier known to denote a certain object (“object” mathematically speaking).Definitions on the other hand will, hence their name, define what this object exactly is.Whether it is a value of a constant, the value of a variable, or the steps taken in a routine (the statement sequence), data defined through definitions will result in specific code in your executable file, which may vary according to the information given in related declarations;writing a variable possessing the data typeinteger is fundamentally different than writing a value of the typereal.The code for properly storing, calculating and retrievinginteger andreal values differs, but the computer is not aware of that.It just performs the given instructions, the circumstance that a certain set of instructions resemble operations on Pascal’s data typereal for instance is, so to speak, a “coincidence”.
Routines are selected based on their signature.A routine signature consists of
Thus the signature of the functionodd readsodd(integer).The function namedodd accepts oneinteger value as thefirst (and only) argument.
Pascal allows you to declare and define routines of the same name, but differing formal parameters.This is usually calledoverloading.When calling a routine there must be exactly one routine of that name that accepts parameters with their corresponding data types.
| signature | description | returned value’s type |
|---|---|---|
abs(integer) | absolute value of argument | integer |
odd(integer) | parity (is given value divisible by two) | Boolean |
sqr(integer) | the value squared | integer |
programpersistentVariableDemo(output);{$ifDef FPC}// allow assignments to _typed_ “constants”{$writeableConst on}{$endIf}procedurefoo;constnumberOfInvocations:integer=0;beginnumberOfInvocations:=numberOfInvocations+1;writeLn(numberOfInvocations);end;beginfoo;foo;foo;end.
The program will print1,2,3 for every call.Lines 2, 4, and 5 contain specially crafted comments that instruct the compiler to support persistent variables.These comments are non-standard, yet some are explained in the appendix,chapter “Preprocessor Functionality”.
Note, the concept of typed “constants” is not standardized.Someobject-oriented programming extensions will give nicer tools to implement such behavior as demonstrated above.We primarily explained the concept of persistent variables to you, so you can read and understand source code by other people.
Routines can be used as many times as you want.They are no tools of mere “text substitution”:The definition of a routine isnot “copied” to the place where it is called, the call site.The size of the executable program file remains about the same.
Utilizing routines can also be and usually is beneficial to the development progress of a program.By splitting up a programming project into smallerunderstandable problems you can focus on solving isolated issues as part of the big task.This approach is known asdivide and conquer.We now ask you to slowly shift toward thinkingmore about your programming tasksbefore you start typing anything.You may need to spend more time on thinking about, for example, how to structure a routine’s parameter list.What information, what parameters, does this routine require?Where and how can a recurring pattern be generalized through a routine definition?Identifying such questions needs time and expertise, so do not be discouraged if you are not seeing everything the task’s sample answers show.You will learn through your mistakes.
Keep in mind, though, routines are no panacea.There are situations, very specific situations, where you do not want to use routines.Recognizing those, however, is out this book’s scope.For the sake of this textbook, and in 99% of all your programming projects you want to use routines if possible.Modern compilers can even recognize some situations where a routine was “unnecessary”, yet the only gain is that your source code becomes more structured and thus readable, albeit at the expense of being more abstract and therefore complex.[fn 5]
printM,printI,printS,printP, will significantly speed up development.programmississippi(output);constwidth=8;procedureprintI;beginwriteLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn;end;procedureprintM;beginwriteLn('# #':width);writeLn('## ##':width);writeLn('# ## #':width);writeLn('# #':width);writeLn('# #':width);writeLn;end;procedureprintP;beginwriteLn('### ':width);writeLn('# # ':width);writeLn('### ':width);writeLn('# ':width);writeLn('# ':width);writeLn;end;procedureprintS;beginwriteLn(' ### ':width);writeLn(' # # ':width);writeLn(' ## ':width);writeLn('# # ':width);writeLn(' ### ':width);writeLn;end;beginprintM;printI;printS;printS;printI;printS;printS;printI;printP;printP;printI;end.
programmississippi(output);constwidth=8;procedureprintI;beginwriteLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn('# ':width);writeLn;end;procedureprintM;beginwriteLn('# #':width);writeLn('## ##':width);writeLn('# ## #':width);writeLn('# #':width);writeLn('# #':width);writeLn;end;procedureprintP;beginwriteLn('### ':width);writeLn('# # ':width);writeLn('### ':width);writeLn('# ':width);writeLn('# ':width);writeLn;end;procedureprintS;beginwriteLn(' ### ':width);writeLn(' # # ':width);writeLn(' ## ':width);writeLn('# # ':width);writeLn(' ### ':width);writeLn;end;beginprintM;printI;printS;printS;printI;printS;printS;printI;printP;printP;printI;end.
Notes:
{$extendedSyntax on} which will allow the program above to compile anyway.label-section has intentionally been omitted.type declarationsdo produce data thatis stored in your program.