Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / Functions For Beginners (DBC)

Author
Message
TDK
Retired Moderator
22
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 20th Dec 2006 17:58 Edited at: 2nd May 2010 14:37
Before I start, I'd like to explain that Gosub with subroutines is not in the same category as Goto. Using subroutines is GOOD programming practice and using Goto is BAD.

Functions however were not designed to be used INSTEAD OF subroutines, but to be used WITH subroutines. So, using functions for everything is NOT a good idea when you are learning to program. (IMHO it isn't good when you know what you are doing either, but that's a matter for debate and as an experienced coder, you can program how you want).

The point is that functions were designed to run in their own isolated part of memory, have the variables they require to work passed to them and most importantly, generate a single piece of data as a result which gets passed back to the main program it was called from.

Definition Of A Function (Wikipedia):

The mathematical concept of a function expresses the intuitive idea that one quantity (the argument of the function, also known as the input) completely determines another quantity (the value, or the output).

Note that this implies that all functions generate a single value for their output.

So, if the code you place in a function needs to change lots of data items (Eg. you need to define lots of global variable for it to work), or it doesn't have any values to pass back to the main program, then it shouldn't really be a function - it should be a subroutine. Period!

For proof, take a look at ANY of the functions which are built into Dark Basic - they all have () on the end, like Point(), RGB(), Object Position X() etc.

Notice that they all take a number of parameters and return just a single value as an output?

So, I'm not saying don't use functions, I'm saying that you should use functions appropriately - as they were intended.


Dark Basic Functions


Whereas a subroutine, (often called a 'procedure'), starts with a label and ends with a RETURN and is called using GOSUB, functions are a somewhat different beast. Although similar to look at code-wise as subroutines, functions in Dark Basic have three main differences:

1. Local Variables

All variables in a function are local as opposed to global. In programming terms global means that they are visible to all of your program, whereas local means that they are only visible inside a function they are used in. The visibility of variables is called the variable's 'scope'.

In Dark Basic Classic however, proper global variables don't really exist officially as they cannot be declared, (unless you are using an IDE which supports them). DBPro does have global variables.

A normal variable in your main program can be seen inside a procedure, but not inside a function. So, although I'll refer to them as global variables, DBC users should think of them as being 'semi-global'.

Another thing to remember about local variables is that they can co-exist at the same time as other variables with the same name.

This is very important to remember as not knowing this can lead to some very hard to find bugs in your programs.

For example, if you set the variable A to equal 10 in your main program with A=10, then call a function in which you say A=20, when you exit the function what will A equal?

If you said 20 then you got it wrong! The answer is 10 because inside the function, the variable A would be a newly created local variable called A - entirely seperate from the previously created variable A outside the function. When you exit from the function, you revert back to the the original variable A, which is of course is still equal to 10.

This feature can be very useful, but if you are used to programming in other languages you can be lured into a trap, so beware.

Variables in BASIC do not need to be declared at the start of your program like in Delphi or C - they exist from the moment you refer to them. For example, if you write a DB program with just one line which says PRINT MYVAR then DB will quite happily initialise the variable containing the value 0 and print 0 on the screen. You don't have to tell DB beforehand that you are going to use the variable MYVAR in your program and that it is going to be an integer variable.

In other languages, local variables are 'destructive', which means that when you exit a function, any local variables are destroyed.

The next time you visit the function, the variables are created again as entirely new entities. However, in Dark Basic local variables in functions are 'non-destructive' which means that when you return to a function, the variables still exist and contain whatever values they did when you were last there. This 'feature' can be very useful if you know it's there, but an annoying source of difficult to trace bugs if you don't!

2. Entry & Exit Parameters

Functions can be used to do a specific task without any external information and then exit without returning any information. If no entry parameters are required, empty parenthesis can be used when calling the function and in the function header - or they can be omitted entirely. DB will accept either format.

Alternatively, functions can do a task calculated on the information supplied and then return information. One example of a return value would be a success value. A 1 returned would denote that the function's task was completed successfully whereas a 0 could denote that something went wrong.

As described above, all variables in a function are local, so you need a method to pass information from your main program to the function and this is done by calling the function with the required variables in a 'parameter list' which is enclosed in parethesis '()'. The function itself must have the exact same parameter list to accept the same variables. So, you would have functions something like these:

No Entry Or Exit Parameters:



Using Entry And Exit Parameters:



It's fairly obvious here that the function called MyFunction() is passed a parameter list of four variables - the first three being integer numbers and the fourth a string. These variable names are used inside the function as local variables to calculate the value of RetVal. RetVal is then returned back to the calling function. The actual calculation is of course nonsense, but demonstrates how things work.

So, how are functions called? Well, it depends on whether you need to pass parameters or not and whether your function returns anything. The first example above neither requires or returns anything so it is called with:

StartScreen()

The second function needs three integer variables and a string so they are passed in the parameter list. The actual variable names used in the call need NOT be the same as used in the parameter list of the function header as the variable's contents are placed into local variables when they get there. Think of it as passing the contents of each variable to the function - not the variables themselves.

The function also returns the contents of the variable RetVal, so we must take that into account when calling the function. This is done by using a variable of the same type in the call. As our example function MyFunction() returns an integer, we use the following call:

ValueBack=MyFunction(MinLen,MaxLen,Score,"Elephant")

After calling the function, the variable ValueBack will contain the returned contents of RetVal from the function. The value returned can be an integer number, a real number or a string, but the subtle point is that in Dark Basic, functions can only return a single value which can be a bit limiting.

The answer in many programming languages is the declaration of true global variables which can also be accessed within functions.

Sadly, you don't have the ability to do this in Dark Basic Classic, though as it happens, the work-around is on a similar theme - using arrays. Remember though, using arrays is only a work-around and there are limitations. You can't pass arrays to functions or return them.

It was discovered a long time ago that in DB Classic, arrays behave like proper global variables and an array declared at the start of a program can be seen, used and modified inside a function and is still intact upon exiting the function. Arrays declared inside a function remain local though and not accessible outside it. So using arrays, a function can return multiple values - or the equivalent anyway.

3. #Include Files

Functions can be used in Include files - something widely misunderstood by the newcomer to programming with Dark Basic.

In a nutshell, the idea is that they prevent you from having to write certain sections of often used code over and over again each time you write a new program. A good example is the keyboard/mouse control code which you use for controlling the game character or ship in your games. If all the actions for moving and firing etc. are all done with functions, then they can all be saved in a single file called, let's say Control.dba for example.

The next time you write a program which uses the same control method, all you have to do is put the Control.dba file into the same folder as your new program and use the following line as the first line of your program:

#Include "Control.dba"

When the program is run, all the functions in the #Include file become available - without you having to re-code them again. A big time saver - especially if you have functions to cover all possible control input methods. You'd never have to write a piece of input code again!

You must remember however, that Include files can ONLY contain lists of function and no code can reside outside of each function header and it's associated EndFunction. To the best of my knowledge, the REM statement is the only exception allowed.

Why Use Functions?

Well speed-wise, there is little or no difference between using a procedure and a function, so the main reason for using them would be for the ability to use local variables or the future grouping together of them in a #include file. (In #Include files you can ONLY have functions - nothing else).

In fact in some cases, a procedure is better due to the lack of the local variable problem.

Some users will swear by using functions for everything, which I find a little pointless, but at the end of the day, go with whichever you are happiest with.

TDK_Man

Larcen Tyler
17
Years of Service
User Offline
Joined: 12th Feb 2007
Location: Somewhere on Earth
Posted: 20th Feb 2007 23:22
So basically, if you're using any variables in the function, they have to be put into the parenthesis(sp?) Is that correct?

Larcen Tyler
Some Eternal Champions just never die
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 29th Apr 2007 05:15
Not necessarily.

You can declare a variable in a function as well.
The parenthesis are just for inputing variables for the function to use.
Fuzzzy Piggy
18
Years of Service
User Offline
Joined: 2nd Mar 2006
Location:
Posted: 29th Apr 2007 18:35
Many thanks for that! I found myself stumbling over the difference between funcs and procs, often wondering why my variables wouldn't work out quite right.

Common-Sense has been removed from service, due to lack of interest. Thank you for your time.
RUCCUS
19
Years of Service
User Offline
Joined: 11th Dec 2004
Location: Canada
Posted: 29th Apr 2007 18:49 Edited at: 29th Apr 2007 19:17
Quote: "However, in Dark Basic local variables in functions are 'non-destructive' which means that when you return to a function, the variables still exist and contain whatever values they did when you were last there. This 'feature' can be very useful if you know it's there, but an annoying source of difficult to trace bugs if you don't!"


Why did they remove that feature in pro? Or did you just word that incorrectly?

The following code in pro;



Prints 0 everytime, but according to what you're saying, it should print 0, then 5 thereafter. Does it do that in DBC? I find it weird that they'd change it to destroy the variables in pro... it'd be fairly useful.

<edit>

Oh, and why isn't this in the DBC board! You're breaking your own rules TDK .

RUCCUS
19
Years of Service
User Offline
Joined: 11th Dec 2004
Location: Canada
Posted: 29th Apr 2007 21:26
Id rather have functions retain their variables and have a command to flush out all local variables to a specific function, or better yet flush out a single variable by name (not happening without pointers... so doubtfull) than have to globalize every value I create within a function that is required later on.

TDK
Retired Moderator
22
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 30th Apr 2007 02:33
Quote: "Why did they remove that feature in pro? Or did you just word that incorrectly?"


Me? Word something incorrectly in a tutorial? Never!

It wasn't removed so much as 'fixed'. I, like WindowsKiller regarded it as a bug - albeit a useful one - that's why I referred to it as a 'feature' (my term for DBC bugs). The point is, all local variables should be destroyed when you leave a function.

Try this:



In DBC, the second time the function is called, the value you entered the first time the function was called is printed. If it doesn't do that it DBP then it has been corrected and now works as it should.

Quote: "Oh, and why isn't this in the DBC board! You're breaking your own rules TDK"


I wasn't breaking any rules when it was posted!

Only DBC related threads which appeared on the first page had been moved - because there are so many and because of a forum bug, moving posts takes such a long time.

This thread had sunken well down the list - until someone resurrected it...

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 30th Apr 2007 02:37 Edited at: 12th Mar 2008 06:40

Login to post a reply

Server time is: 2024-11-25 19:44:16
Your offset time is: 2024-11-25 19:44:16