Search:
All Any

Part of mariaus.info network Subscribe via RSS
Follow on twitter Request a tutorial
Business card # 1
Visitor request: Creating photo collages in photoshop
Create cloud brushes in Photoshop
Quick tip: The dream effect
Create a planet in Photoshop
Photography and art inspiration # 4
Photography and art inspiration # 3
Photography and art inspiration # 2
Photography and art inspiration # 1
Go to first pageAdd to favorites (this)Contact page ownerRequest a tutorialSubscribe to the Tip Kit news
Request a tutorial
Introduction to Delphi, Part 5 - Procedures and functions

Learn about the basic usage of procedures and functions in Delphi.
In the previous tutorial, you've learned about constants, variables, their definitions and assignment. We haven't talked about any environment from which these variables can be accessed and used. Now it's time to do some work and perform some actions. The article you're going to read below covers basic usage of procedures and functions in Delphi. So let's get started and do some programming!

In Delphi, there are a few ways to do some real work (calculations etc.): in a function, in a procedure, in a project source. We will be talking about the first two for now. A function or procedure is a block of code, that can be called (executed) from another source. Basically, they are meant to do a single action or realise a single algorithm. For example, there could be a function to generate ten random numbers: it might consist of lots of code, but in the end it does a single job. At first let's find out the difference between a function and a procedure. Procedures are meant to be only called to do something, but the function can also return some result. For example, if you want to print 10 lines of random numbers, you could use a procedure to do this, but if you want to get a random number and store it in memory, you could use a function to generate it and return it back to the code it was called from. Function results can be assigned to variables or simply ignored. To use a function or a procedure, we must first define it. So let's define two global functions and i'll walk you through every line, explaining what it does. As we already know, global stuff is defined either in classe's public clause or simply in a unit outside all classes. If you define a procedure for a class - it is no longer a procedure. It is called a method in terms of object orientated programming. Though there's not much of a difference between them two. Look at the following lines of code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  procedure DisplayMsg(AMessage : string);
  function Add(AVar1, AVar2 : real): real;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.
As you see, we have a function and a procedure defined just before the var directive in this example. Now let's find out what both of these lines mean.

procedure DisplayMsg(AMessage : string); - This line defines a procedure, that will have a parameter of string type, passed to it. What does that mean? It means that when you call this procedure, you'll have to specify some text. To make things even clearer - this procedure will show us a message with an OK button on screen. So, if we want to show some message, we need to know what text to output, right? To know what text to show, we add a parameter AMessage that is basically same as a variable. Now, when users want to call this procedure, they already know wht text they'll want to show and specify this text in the place where AMessage is. To Call a procedure or a function, we simply write its name, followed by an opening bracket, followed by all its parameter values and a closing bracket. Notice that each line of actual code (not directives) in Delphi must be terminated by a semicolon. So if we want to show a message "Hello to the world!" on the screen, we would call the DisplayMsg procedure like this:
  DisplayMsg('Hello to the world!');
You can see that in the procedure call, variable (parameter) AMessage is replaced by its value. You can also replace it with some other variable that you have defined earlier.

function Add(AVar1, AVar2 : real): real; - Now this is a little bit different. We see a function to add a number to another number and return the result. We see thet this function takes two parameters: AVar1 and AVar2. These parameters will later be added to each other in the function and returned. The last real word after the closing bracket defines a type that this function returns.

So the definition of a function or a procedure looks like this:
  procedure ProcedureName(Parameter1: type1; Parameter2: type2; ...; ParameterN: typeN);
  function FunctionName(Parameter1: type1; ...; ParameterN: typeN): ReturnType;
As you can see, we use semicolons to separate each parameter and in previously declared function Add we've used commas. There aren't any mistakes here. The rules apply the same way as in variable definitions: you can list parameters of a same type, separated by commas, but you must separate different type parameters by semicolons.
OK so we've defined a function and a procedure. Now what? Let's make them work!. As the definition part is done in the interface section of the unit, the real code is done in implementation. So see the example below and try to understand it.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  procedure DisplayMsg(AMessage : string);
  function Add(AVar1, AVar2 : real): real;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure DisplayMsg(AMessage: string);
begin

end;

function Add(AVar1, AVar2 : real): real;
begin

end;

end.
Here we have started realising our methods. The single line function and procedure definitions are only meant to show us how the function calls will look like (how they are called, what parameters they have, what they return) and the lines with begin ... end clauses area meant to show us what the methods actually do. In this case they do absolutely nothing, because we've coded nothing yet. So as you have probably guessed, this is default implementations of our procedure and a function. First line is the same as in the definition, then it is followed by the word begin, then some empty space 9that we will insert some code later) and finally, by the word end; (note the semicolon). Same goes to both procedures and functions. Begin and end; blocks do exactly what you might have already guessed - they mark the start and the end of some code block (in this case, procedure or a function). Let's advance this example a bit more. Let's replace the implementations with the ones below:
procedure DisplayMsg(AMessage: string);
begin
  ShowMessage('This is our message: ' + AMessage);
end;

function Add(AVar1, AVar2 : real): real;
begin
  result := AVar1 + AVar2;
end;
Now we have some code in them. What does it do? Let's start with the procedure. We see a single line of code that basically calls another procedure, called ShowMessage and passes our defined message with a prefix "This is our message: ". Note that you can "glue" two strings together by using the + operator. For example if you write some_string_var := 'Two ' + 'words'; - the value of some_string_var will become "Two words". We've done the same in the brackets of ShowMessage in the current example. Whatever the user passes to AMessage, will be prefixed by "This is our message: " and then sent to the ShowMessage procedure. But hold on a moment ... where did this ShowMessage come from? We haven't seen it before. Correct, we haven't seen lots of things yet, but some of them already exist in Delphi. ShowMessage is a procedure, created by Borland team and integrated to Delphi so that you wouldn't need to create something like this for yourself. If you deleted the Dialogs word from the uses clause in the top of your unit - this procedure would not work, because Dialogs is exactly the unit this procedure is implemented in. In order to really learn Delphi, you will have to know many procedures like this one, or at least know where to find information about them. The reason is simple - there is no need to invent anything that has already been invented. Imagine how much time you would spend, writing all the already implemented procedures yourself. It's just a waste of time. But let's get back to the point. If we call the DisplayMsg procedure with a parameter "Hello world", it will be executed like this:
A text "This is our message: " would be prefixed to the start of "Hello world" and the result of those two "glued" strings would be sent to ShowMessage procedure. And the ShowMessage would display a message with OK button that says: "This is our message: Hello world".

The function is a little different. We see that the sum of our variables (parameters) AVar1 and AVar2 is being assigned to a variable result. But we also haven't defined this variable anywhere! You guessed it - it has already been defined for us. And in this case it isn't even a variable - it's the result of our function. So what all this line of code means is that both the parameters are summed and returned by the function to the place where it was called from. Now to illustrate this returning mechanism, see the following example.
function ModifyWord(AWord : string) : string;
begin
  result := AWord + ' (modified)';
end;

procedure DisplayWord(AWord: string);
begin
  ShowMessage(ModifyWord(AWord));
end;
Here we have a function and a procedure again. I've not defined them to leave only the most important code and to keep it short. But i hope you understand that the rest of the unit, including definitions have to be here too in order for the code to work :) So imagine we call DisplayWord procedure with parameter "Hello". What happens here?

1. The procedure DisplayWord is passed a parameter "Hello".
2. Since Delphi reads the lines in the exect opposite as we do, it firsts tries to call ModifyWord function with a parameter that we have already passed.
3. The function ModifyWord is called and passed a parameter "Hello".
4. ModifyWord adds the text " (modified)" to the end of the parameter, it results in "Hello (modified)".
5. ModifyWord assigns "Hello (modified)" to the result of itself and returns the result to the caller.
6. The caller is DisplayWord procedure and with the result from ModifyWord returned, it sees the ShowMessage... line like this: ShowMessage("Hello (modified)").
7. The ShowMessage is called with a parameter, returned by the ModifyWord function.
8. The "Hello (modified)" message is displayed on the screen with an OK button.

It might have been simpler to understand if the procedure looked like this:
procedure DisplayWord(AWord: string);
var _temp : string;
begin
  _temp := ModifyWord(AWord);
  ShowMessage(_temp);
end;
First thing to note is that we have a variable _temp, defined in the procedure. This is called a local variable. Only this procedure can see and work with it. It is defined between the Procedure line and the begin word by the same rules, as the variables are defined in a unit. Note that you don't have to prefix local variables with "_", but it will be easier for you to differ local variables from global if you do so. So in the above example, we create a new string variable _temp to store a temporary value. Then, we assign whatever the function ModifyWord("Hello") returns. And then we display the contents of _temp variable in a message box. Another thing to note is that you don't have to define a local variable in this situation. You can do this:
procedure DisplayWord(AWord: string);
begin
  AWord := ModifyWord(AWord);
  ShowMessage(AWord);
end;
Parameters are also variables so they can also be assigned values. Since Delphi sees the lines from the opposite way that we do, it first takes the value of AWord ("Hello") and passes it to ModifyWord function. Then it takes the result, returned by ModifyWord and assigns to AWord. So we've just changed the value of the same variable we already had. And finally we passed its value to ShowMessage.

You can safely assign new values to function or pracedure parameters as long as you know for sure you won't need the old ones :) Now try to see if you've understood anything and try to figure out what message we would see on the screen if we called DisplayMsg('cat') in the following code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  function ModifyText(AText : string): string;
  procedure DisplayMsg(AMsg : string);

var
  Form1: TForm1;
  glob1 : string = 'my ';

implementation

{$R *.dfm}

function ModifyText(AText : string): string;
begin
  AText := AText + ' eats a lot';
  result := AText;
end;

procedure DisplayMsg(AMsg : string);
begin
  AMsg := ModifyText(AMsg);
  AMsg := glob1 + AMsg;
  ShowMessage(AMsg);
end;


end.
If you thought of 'my cat eats a lot' - you were right! Congratulations! If not, let's see what happened here.

1. You've passed a text "cat" to the DisplayMsg procedure.
2. It then called ModifyText with the same parameter "cat".
3. ModifyText appended text " eats a lot" to the word "cat" and assigned it to the result.
4. ModifyText returned its result back to DisplayMsg procedure's first line and that result was assigned back to AMsg. So the AMsg now contains text "cat eats a lot" instead of "cat".
5. Another string from a global variable glob1 was prefixed to the AMsg and assigned back to it. So now AMsg contains text "my cat eats a lot".
6. Finally the ShowMessage was called with a parameter "my cat eats a lot".

Someday you will ask yourself a very important question: can a function return more that one value? What if i need it to return two or three numbers, instead of one? The answer is: by default no, but there are still other ways to do it. By using those ways we can even make a procedure return values! Now i'm going to explain only one of the few possible ways, because you still only have enough knowledge to understand the first way. The answer to our prayers is the var directive. If written before a parameter name, it enables this parameter to be read from outside the function. There are two types of parameters: passed by value and passed by reference. The ones we've covered so far were passed by value. That is in all cases, if we wanted to call a procedure with a parameter, we would have to replace the parameter's name with some value. And in the function or procedure we were able to change this parameter safely, without affecting the outside world. But if we pass a parameter by reference - then some variable is passed instead of its value and we can no longer replace parameter names with values. We have to replace them with other variable names instead. Consider the following example:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  procedure ModifyText(var AText : string);
  procedure DisplayMsg(AMsg : string);

var
  Form1: TForm1;
  glob1 : string = 'my ';

implementation

{$R *.dfm}

procedure ModifyText(var AText : string);
begin
  AText := AText + ' eats a lot';
end;

procedure DisplayMsg(AMsg : string);
var _temp : string;
begin
  _temp := AMsg;
  ModifyText(_temp);
  AMsg := glob1 + _temp;
  ShowMessage(AMsg);
end;


end.
As you can see here, we have a var directive before the AText parameter in procedure ModifyText. As you can also see, we got rid of the function and replaced it with a procedure instead. Let's see what happens here.

1. We pass the text "cat" again to the DisplayMsg.
2. To make it less confusing, the procedure assigns the value of AMsg to a temporary variable _temp.
3. Now we call another procedure ModifyText with parameter _temp.
4. Normally, a word "cat" would be passed to ModifyText, but when we have a var directive, all the variable _temp is passed instead of its value. Actually, its address is passed instead of its value, but let's not confuse you with the technical side yet.
5. Now in the ModifyText procedure, the AText variable, instead of having a value of "cat", points to DisplayMsg procedure's variable _temp. So whatever we do with the value with AText, the same will reflect on _temp in DisplayMsg. In this case we append some text to the AText parameter. So this means that instead of appending it to AText, delphi appended to _temp. In other words, AText becomes something like an alias of the _temp variable and instead of having its own value, AText sees the value of _temp. We don't have to assign anything to result here, because we've assigned directly to _temp and procedures don't have a result directive.
6. Now, after appending " eats a log" to _temp, which already had "cat" in it, the result of _temp is "cat eats a lot"
7. Now the result of _temp is "glued" to the result of glob1 and assigned back to AMsg. So now AMsg contains text "my cat eats a lot".
8. Finally, we display the message.

Hopefully, you've learned some valuable information from this tutorial. In the next tutorial, we will talk about something very similar to functions and procedures - methods. Click here to continue reading

Article written by: Marius S.
This article is an intellectual property of its respective author. All images, used here are property of tip-kit.com if not stated otherwise.
Share this article
Digg del.icio.us Facebook Furl Google Reddit Slashdot StumbleUpon Technorati
How easy was it to understand? Was it useful?










Leave a reply
Your name:

Message:

Confirmation code
Please enter the above code:
There are no comments yet. You can use the above form to leave a reply.
Copyright © 2009 Tip-Kit.Com | Valid XHTML 1.0 | Powered By Isis | RSS