Previous: Variables

Workshop 2: Functions

This is a function:

function add_numbers( )
{
   var a, b, c;
   a = 3;
   b = 5;
   c = a + b;
}

► Functions are defined using the word function followed by the name of the function and a pair of parentheses ( ). The parentheses are used to pass additional variables to the function, if required.

► The body of the function (its list of commands) is written inside a pair of winged brackets { }. The body consists of one or more lines of lite-C code that end with a semicolon. Programmers usually indent the code in the function body by some spaces or a tab, for making clear that it is inside something.

► The names used for the functions follow the same naming convention as for variables. Don't use the same name for a variable and a function.

Let's try to write a function that computes the number of days spent by me (or you) on Earth. I write the keyword function and then the name of the function; let's name it compute_days:

function compute_days()
{

We will use some variables, so we'd better define them now:

var my_age = 33; // your age (in years) goes here
var days_a_year = 365.25;

Nothing new so far, right? We have defined two var variables and they have received initial values, because I know my age in years and I also know that every year has about 365.25 days. Now comes the scary part: how will I be able to tell the computer to compute the number of days? How would I do it with a pocket calculator? I would enter something like this:

33 * 365.25 =

Now let's take a look at our variables; if I replace 33 with my_age and 365.25 with days_a_year, I will get something like this:

number_of_days = my_age * days_a_year;

Ok, so our function should end like this:

   var number_of_days = my_age * days_a_year;
   printf("I am %.f days old!",number_of_days);

}

I have remembered to add the second curly bracket, so now the body of the function is enclosed by the two required curly brackets. I am really curious to see if this function works, so let's test it. Fire up Zorro, and then select [New Script] in the Script list. Wait until the editor opens. Then copy and paste the lines below into the editor window. Select the entire script below with your mouse, right click and choose Copy (or hit [Ctrl-C]), switch to the editor, right click into the empty window named "script1", then choose Paste:

function compute_days()
{
  var my_age = 33;
  var days_a_year = 365.25;
  var number_of_days = my_age * days_a_year;
printf("I am %.f days old!",number_of_days); }

The code looks pretty simple, doesn't it? We already know how to work with those variables, we know how to add comments... So let's save it (File / Save As) into the Strategy folder of the Zorro installation, under a name like myscript2.c. Don't forget the ".c" at the end - it means that this file contains C code.

If you did everything right, you should now find myscript2 in the Script list. Select it. Time to [Test] our script. But what is that? Instead of the expected result we'll get an error message "No main or run function!".

Does this error message mean that a script always needs a main() or run() function? Yes, main is a predefined function name. If a function is named main, it will automatically start when we start our script. The function named run is special to Zorro; it contains our trade strategy and is automatically run once for every bar period. If a script has neither a main nor a run function, Zorro assumes that you made a mistake and will give you this error message.

Now, let's enter a main function at the end of the script:

function main()
{
   compute_days();
}

The way I see it, this code 'calls' (meaning it starts) our compute_days function. Ok, now that we are here let's see how we call a function: we write its name followed by a pair of parenthesis and then we end the line of code with a semicolon. Sounds logical, doesn't it?

Important tip: write the lines of code for your functions first and call them later. The computer reads the code the same way you read a book: it starts with the top of the script page and goes down to the bottom, reading the code line by line. If I would write my script the other way around, like this:

function main()
{
   compute_days();
}

function compute_days()
{
   ...
}

the computer will say: oh, that's function main. I know function main; I need to run it every time. What does it say now? compute_days(). What's with this function? I don't know it yet! I don't know what it wants from me. I'm going to display an error message and I will take the rest of the day off.

Don't forget to define your function first, otherwise the computer will complain when you try to use it. You will encounter such compiler errors frequently when you write scripts - even experienced programmers make such mistakes all the time. Sometimes it's a forgotten definition, sometimes a missing semicolon or bracket. Get used to compiler errors and don't be helpless when you see one. The computer (usually) tells you what's wrong and at which line in the script, so you won't need rocket science for fixing it.

A short summary of the new things we've learned:

► We define simple functions by writing "function name(...) { ... }".

► If a function has the name main or run, it is automatically executed. All other functions must be called from an already-running function to be executed.

► Don't panic when you see a compiler error - with a little logical thinking they are easy to fix. It is uncool to ask on a forum for help with compiler errors!

Passing variables to and from functions

A function can also get variables or values from the calling function, use them for its calculation, and give the resulting value back in return. Let's see an example of a function that gets and returns variables:

var compute_days(var age)
{
   return age * 356.25;
}

The var age between the parentheses is for passing a value to the function. This value is stored in the variable age, which can be used inside the function like any other variable.

For returning a value from a function, just write it behind a return command. It can be a number, or a variable, or any arithmetic expression that calculates the returned value. The function then gives that value back to from where it was called.

You did notice that we defined this function not with the keyword "function", but with "var"? But is var not a variable definition? Yes, but when a function is expected to return something, it must be defined with the type of the returned variable. So if a function returns a variable of type int, define it with int; if it returns a var, define it with var. Still, the compiler knows from the (..) parentheses that this is a function definition and no variable definition.

If a function expects variables, put their definition - type and name - in the function definition between the parentheses. The space between the parentheses is named the parameter list of the function. If there are several variables in the parmeter list, separate them with commas. When you then call that function, just put the values of the variables you want to pass to the function between the parentheses.

If a function returns something, you can just place a call to that function in stead of the value that it returns. This sounds sort of complicated? Let's try it right away with our new compute_days function. This is our new script:

var compute_days(var age)
{
  return age * 365.25;
}
 
function main()
{
  var my_age = 33;
  var number_of_days = compute_days(my_age);
  printf("I am %.f days old!",number_of_days);
}

We've just set our number_of_days variable direct from the returned value by compute_days(my_age). This makes our code shorter and more elegant! Still, the result is the same:

Note that my_age is a variable inside the main function, while age is a variable inside the compute_days function. Both variables don't know of each other: a variable defined in a funciton only exists within that function. But both have the same value, as age gets its value from my_age when the function is called.

The printf function

Now what is this mysterious printf(..)? It has parentheses attached, so it's obviously also a function that we call for displaying our result. However we have nowhere defined this function; it is a function that is already "built-in" in C. Just as the built-in variables that we mentioned in the last workshop, there are also many functions already built in the script language.

The "I am %.f days old!",number_of_days are the two variables that we pass to the printf function. The first variable is a string, used for displaying some text: "I am %.f days old!". The second variable is a var: number_of_days. Variables passed to functions are separated by commas. You can read details about the printf function in the manual; for the moment we just need to know that the strange "%.f" in the string is a placeholder. It means: the function inserts here the value - with no decimals - of the var that is passed as second variable to the function. So, if number_of_days has the value 12045, our printf function will print "I am 12045 days old!".

We can make our code even shorter. Remember, if a function returns a var, we can just place a call to this function in stead of the var itself - even inside the parentheses of another function. We'll save one variable and one line of script this way. Programmers do such shortcuts all the time because they are lazy and prefer to type as less code as possible:

function main()
{
  var my_age = 33;
  printf("I am %.f days old!",compute_days(my_age));
}

 !!  Here's an important tip when you call functions in your code that return something. Do not forget the parentheses - especially when the parameter list is empty! In C, an function name without parentheses means the address of that function in the computer memory. add_numbers and add_numbers() are both valid and won't give an error message in the code! But they are something entirely different. For avoiding errors, all Zorro's 'built-in' functions begin with a lowercase character (such as enterLong()) and all built-in variables begin with an uppercase character (such as BarPeriod).

Enough for today. The next workshop will teach us how a script can make decisions (called 'branches' in computerish). Being able to decide something is important for trading. So we're now going in huge steps towards writing our own trade strategy.

Next: Branches and Loops


Further reading: ► Functions, return, printf