Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
v3:subroutines [2022/01/21 21:58] – [Defining subroutines] shawn | v3:subroutines [2024/07/30 22:43] (current) – [Overloading] neils | ||
---|---|---|---|
Line 3: | Line 3: | ||
While you can use the [[GOSUB]] command in pair with [[RETURN]] to call parts of code as subroutines, | While you can use the [[GOSUB]] command in pair with [[RETURN]] to call parts of code as subroutines, | ||
- | ===== Defining | + | ===== Defining |
Subroutines are named routines that accept zero or more arguments. The simplest syntax to define a subroutine is the following: | Subroutines are named routines that accept zero or more arguments. The simplest syntax to define a subroutine is the following: | ||
- | SUB < | + | SUB < |
< | < | ||
END SUB | END SUB | ||
- | It is worth noting that a subroutine does not require arguments. In this case you still must add the empty parentheses after the routine name, though, like so: | + | It is worth noting that the argument list is optional. If you omit the arguments, |
SUB < | SUB < | ||
Line 17: | Line 17: | ||
END SUB | END SUB | ||
- | ===== Calling | + | ===== Calling |
You can use the [[CALL]] keyword to call a subroutine. It behaves similarly to [[GOSUB]] with an important difference: '' | You can use the [[CALL]] keyword to call a subroutine. It behaves similarly to [[GOSUB]] with an important difference: '' | ||
Line 25: | Line 25: | ||
END SUB | END SUB | ||
| | ||
- | CALL greet(" | + | CALL greet(" |
- | CALL greet(" | + | CALL greet(" |
The '' | The '' | ||
- | ===== Exiting | + | ===== Exiting |
The subroutine will be exited at the '' | The subroutine will be exited at the '' | ||
Line 39: | Line 39: | ||
END SUB | END SUB | ||
CALL test(-1) | CALL test(-1) | ||
- | ===== Local and global variables | + | ===== Local and Global Variables |
Variables defined inside a subroutine are local variables, i. e. they are only accessible within that subroutine. Global variables (the ones defined outside subroutines) are visible from within all subroutines. | Variables defined inside a subroutine are local variables, i. e. they are only accessible within that subroutine. Global variables (the ones defined outside subroutines) are visible from within all subroutines. | ||
Line 53: | Line 53: | ||
==== Shadowing ==== | ==== Shadowing ==== | ||
- | A local variable | + | A local variable |
a = 42 | a = 42 | ||
Line 64: | Line 64: | ||
- | ===== Static vs. dynamic | + | ===== Static vs. Dynamic |
- | At this point it is important to understand how arguments | + | It is important to understand how arguments |
- | * //Dynamic// arguments: the arguments are created dynamically in memory. Before the subroutine is called, a new area in memory - a //stack frame// - is allocated and this area holds the passed arguments. The advantage of dynamic memory allocation is that it allows recursive subroutine calls, i. e. the subroutine can call itself without | + | * //Dynamic// arguments: the arguments are created dynamically in memory. Before the subroutine is called, a new area in memory - a //stack frame// - is allocated, and this area holds the passed arguments. The advantage of dynamic memory allocation is that it allows recursive subroutine calls, i. e. the subroutine can call itself without |
- | * //Static// arguments: the arguments | + | * //Static// arguments: the arguments |
- | The default | + | The default |
SUB < | SUB < | ||
<adm note> | <adm note> | ||
- | The '' | + | The '' |
</ | </ | ||
Line 83: | Line 83: | ||
</ | </ | ||
- | ==== Static | + | ==== Static |
You can mix static and dynamic behaviour using the '' | You can mix static and dynamic behaviour using the '' | ||
Line 93: | Line 93: | ||
<adm note> | <adm note> | ||
- | Static local variables' | + | Static local variables' |
</ | </ | ||
- | If a subroutine is defined as '' | + | If a subroutine is defined as '' |
SUB test (arg AS INT) STATIC | SUB test (arg AS INT) STATIC | ||
Line 109: | Line 109: | ||
===== Overloading ===== | ===== Overloading ===== | ||
- | When passing arguments to a subroutine, the compiler will match the number of arguments | + | Subroutine overloading, commonly known as method overloading |
- | If the number | + | Overloaded subroutines have the same name but differ in the type, number, |
- | But what if you need subroutines that act differently when different number or type of arguments are passed? This is possible using overloading. A subroutine can have as many variations as you want. In this case the compiler will find the best match among the candidates for a call. For example: | + | ==== Compile-Time Polymorphism ==== |
- | | + | The appropriate subroutine to call is determined at compile-time based on the arguments provided in the call. |
- | PRINT "a is an integer: "; a | + | |
+ | Consider the following example: | ||
+ | |||
+ | | ||
+ | PRINT msg | ||
END SUB | END SUB | ||
| | ||
- | SUB test (a AS STRING * 16) OVERLOAD | + | SUB PrintMessage(msg AS STRING * 16, num AS INT) OVERLOAD |
- | PRINT "a is a string: | + | PRINT msg; " "; |
END SUB | END SUB | ||
| | ||
- | CALL test(5) | + | CALL PrintMessage(" |
- | CALL test("hello") | + | CALL PrintMessage("The number is", 42) |
<adm warning> | <adm warning> | ||
- | You have to use the '' | + | You must use the '' |
</ | </ | ||
Line 133: | Line 137: | ||
It is possible to overload the built-in XC=BASIC functions in your code, too. | It is possible to overload the built-in XC=BASIC functions in your code, too. | ||
</ | </ | ||
- | ===== Forward | + | ===== Forward |
A subroutine can not be called before it was defined. This often makes it hard to organize your code in a clean and readable way. You may want to put subroutines at the end of your code and that's a perfectly valid requirement. | A subroutine can not be called before it was defined. This often makes it hard to organize your code in a clean and readable way. You may want to put subroutines at the end of your code and that's a perfectly valid requirement. | ||
- | This is where forward declaration comes in handy. Forward declaration means that you declare a subroutine' | + | This is where forward declaration comes in handy. Forward declaration means that you declare a subroutine' |
REM -- the top of the program | REM -- the top of the program | ||
Line 149: | Line 153: | ||
<adm warning> | <adm warning> | ||
- | The implementation must use the same number and type of arguments as the declaration. Overloading is possible though: you can declare overloaded variations of the subroutine and imlement | + | The implementation |
</ | </ | ||
- | ===== Subroutine | + | ===== Subroutine |
- | Subroutines, | + | Subroutines, |
- | * //Global// visibility: the subroutine is callable from within the entire code module | + | * //Global// visibility: the subroutine is callable from within the entire code module it was defined |
* //Shared// visibility: the subroutine is callable from within all code modules. | * //Shared// visibility: the subroutine is callable from within all code modules. | ||
Line 168: | Line 172: | ||
END SUB | END SUB | ||
- | This way you make sure it is callable from within other code modules. Read more about [[code_modules|Code Modules here]]. | + | This will ensure the subroutine |
<- flowcontrol|Previous page ^ subroutines|Subroutines ^ functions|Next page -> | <- flowcontrol|Previous page ^ subroutines|Subroutines ^ functions|Next page -> | ||