Functions and Subroutines

 

Functions and Procedures(also called subroutines) are techniques that allow scripts to be broken down into different distinct sections. These sections can be used to aid the clarity of the script, as scripts are by nature not the easiest document to read. You can also use functions and procedures to increase the efficiency of a script by putting code that is repeated in the script into one procedure and interpret that procedure more than once.

 

Subroutines

Blocks of code can be defined inside parameters that define the beginning and end of a subroutine. The code that exists inside the subroutine can then be called and thus interpreted. By calling the subroutine more than once, the subroutine can be reused and thus saving the repetition of code in the script.

Sub1.vbs is an example of a simple subroutine that generates a line of cubes.

The subroutine construct is defined between the statements “Sub” and “End Sub”. Subroutines are named individually, and the user defines the name of the subroutine immediately after the “Sub” statement.

E.g.

     Sub MakeCube

This will start the subroutine construct and name the subroutine “MakeCube”. There are some rules regarding the naming of subroutines:

1>                Subroutine names cannot start in numeric values.

2>                Subroutine names cannot contain spaces.

It is between the “Sub name” and “End Sub” constructs that the block of code that is the subroutine is defined. Note that the code inside the subroutine cannot be interpreted unless directly specified, i.e. if a script is not told to call the subroutine and encounters the “Sub” statement during the code that follows will not be interpreted.

Subroutines are called by simply entering their name during the course of a script. For example, using the MakeCube subroutine above as an example, entering the keyword MakeCube in a script will tell the script to interpret the MakeCube subroutine. Effectively the scripting engine will move to the Sub MakeCube definition in the script and process the text until it encounters the End Sub keywords, upon which it will revert back to its original position in the script.

It is often more useful to call a subroutine by adding the statement “Call” before the name of the script.

E.g.

Call MakeCube

This makes the script easier to read because the call statement is used to directly specify the calling of a subroutine. Sometimes just using the subroutine name in a script to call the subroutine is a bit ambiguous: the “Call” command helps to remedy this.

Subroutines can be passed information to use inside the subroutine itself. These arguments are defined after the subroutine name. In the actual definition of the subroutine the arguments are enclosed in brackets.

Sub2.vbs is an example of a subroutine using arguments.

In the case of the example above, there is one argument in the MakeCube subroutine – called amount. Note that this argument does not have to be defined like a variable, even though it acting like a variable.

If the subroutine is being called without the use of the call statement then the name argument is simply described after the subroutine name,

E.g.

MakeCube 10

If the “Call” statement has been used to call the subroutine, then the arguments need to be encompassed in brackets.

E.g.

Call MakeCube(“Echo”)

Information that is passed to subroutines via arguments can then be used to drive factors of the subroutines. In the case of the MakeCube example, the amount argument is passed into the loop .

Care needs to be taken when passing information into subroutines – in particular to the data type of the information being passed into the subroutine. Subroutines are written with specific data types in mind for the arguments. For example, with the MakeCube example, we expect to be passed an integar for the range of the loop. If we are passed a string instead of a value, the change in data type has a major effect.

E.g.

MakeCube 2.22

Will generate a series of cubes but round it up to the nearest whole cube. Okay, it is not a fatal error but the result is not expected. If a subroutine is passed string information into an argument, but the subroutine is designed to be given numeric values to be used in an expression, then the subroutine will generate an error. This will stop the script. Care has to be taken in the form of considering the data type, and perhaps it is wise to sometimes use some data type conversion techniques to ensure that the script does not halt with an error if given information not consistent with its design.

Variables can be used to pass information into subroutines.

Sub3.vbs is an example of this.

If a variable is used in a subroutine argument, it looks at first glance that it is only the actual value of the variable that is passed into the subroutine. This is in fact untrue, as the actual variable itself is referenced throughout the subroutine by default and as such any changes that happen to the argument inside the subroutine also change the variable used to define the argument.

XTRAS:

Take sub3.vbs and using last weeks lessons on loops, see if you can generate a 3D pyramid structure using a 2 dimensional loop to generate flat areas of cubes. Once you have done that, implement the index condition from last week so that cubes are only made on the outside of the pyramid and not on the inside where we cannot see them. the complete example is in pyramid.vbs.

 

Sub4.vbs is an example of this.

Notice how we define “v” as a variable with a value of 10. A logmessage command then reports this value to us on screen.

We then run a subroutine called MultByTen and pass the v variable into the argument of that subroutine. There is only one line inside the subroutine, which takes the argument, in this case called x, and multiplies it by 10. The subroutine then exits.

A second logmessage command then informs us that the value of v has now increased to 100. It has become apparent that our v variable has been affected by the manipulation of the subroutine, even though the argument is called x.

This process is called passing arguments by reference . It means that the argument references the variable inside the argument throughout the operation of the subroutine – there is an indelible link between the two.

An alternate to this method of passing information, is to instruct VBScript to simply pass a copy of the value stored in the variable into the argument but not to pass the variable itself. This method is known as by value . You can invoke this method by simply adding the ByVaf statement in the definition of the subroutine argument.

For example, change:

Sub MultByTen( x )

To

Sub MultByTen( ByVal x)

Running the script again will now show no change in the value of v. It is only the value of v that is passed into the subroutine now and not the variable v itself.

 

Functions

Subroutines are great for reusing code but they have one disadvantage – they don’t pass information back from the subroutine. Functions are another type of subroutine that allow a block of code to be called, but they do have the ability to return values. The majority of functions are used to return a value based upon input arguments. The information passed back is defined by the user, and can range from a specific numeric value through to logical statements based on the arguments.

 

Load func1.vbs

 

This is an example of a simple function – in this case it takes its argument and multiplies it by 10, passing the result back to the user.

 

The block of code in a function exists between the Function  and End Function statements, in a very similar manner to the way sub … end sub operates a subroutine. In the case of the above example, the function is named “MultByTen” and contains 1 argument called input:

 

Function MultByTen (input)

 

The function name is very important to functions as it defines the name that the user can reference to receive information. There are already many functions built into VBScript – cos, sin and tan for example. We can call our user defined function is a similar manner to using the pre–defined functions:

 

X = MultByTen(5)

 

In the above example, we have the ability to directly link the x variable to the function via an equality symbol. In order to achieve this, we also need to enter an equality expression in the function code itself to define what value we are outputting – and we do this by defining a value to a pseudo variable named after the function name, e.g.

 

MultByTen = input * 10

 

We can add further code inside the function itself to manipulate the output result if desired, but we must express this output information via the pseudo variable. The variable is automatically dimensionalised by the function, so there is no need to declare it with a dim statement.

 

Examples func2.vbs and func3.vbs are further uses of simple scripts.