Writing and Using Functions in Matlab
by Matt Dunham
While we can perform a lot by simply writing script files or executing commands at the command prompt, there are many reasons why writing functions to perform computations and actions is advantageous. Many of these would be discussed in a wider course on programming. We simply list a few reasons here.
- We can parameterize functions to call them multiple times with different inputs.
- In general, its easier to reuse functional code.
- We can compose functions together.
- Functional code is often better organized, and easier to read and understand.
- We can break large problems into a number of smaller problems and write functions to solve each, (i.e. functional decomposition).
- The variable scope of a function is isolated from other functions so we can reuse variable names.
- In Matlab at least, executing functions is faster than executing scripts.
- In Matlab, we can pass functions as inputs to other functions.
Contents
- Variable Scope
- Running Functions
- Creating Functions
- Multiple Functions Per File
- Nesting Functions
- Recursive Functions
- Function Handles / Anonymous Functions
- Function Arithmetic
- Currying
- Variable # of Input Arguments
- process_options
- Redirecting Variable Inputs
- Variable # of Output Arguments
- Matlab Path and Search Order
- Private Functions & Packages
Variable Scope
Matlab commands are executed in one of three places: the command prompt, within a script, or in a function. In the first two cases, the scope of the variables is the base stack or workspace. Functions, however, maintain their own stack, isolated from the others. This means that a variable created in one function does not affect a variable in another, (or the base workspace) even if they have the same name. (There are a couple of technical exceptions, which will not concern us: global variables and the assignin() function – use of either is not recommended).
Running Functions
Below we give some examples of executing functions. Usually we specify the function name, its inputs, and name its outputs. However, functions may return any number of outputs, including 0, and may take any number of inputs, including 0. Some functions can be executed as ‘infix’ operators like ‘+’, or with their own special syntax as with the concatenation function, [ ]. In these last two cases, the special syntax is a kind of shorthand for the execution of the underlying function: ‘a+b’ executes plus(a,b) and ‘[a b]‘ executes horzcat(a,b) .
When a function takes no arguments, the use of parentheses is optional as in version or version(). If we do not supply any names to the outputs of a function and it returns outputs, the first, and only the first, of those outputs is assigned to the ans variable. In general, if a function returns n values, we can assign 0 to n of those by supplying 0 to n variable names enclosed in square brackets as in the examples below.
A = ones(1,2) % call the function ones B = 2+2 % infix call to plus version; % use of () optional if no arguments nums = [1 3 4 2 8 4 3 1 9 2 3 1 3]; % call to the horzcat function unique(nums) % output assigned to 'ans' C = unique(nums); % grab only the first of three outputs [C,D] = unique(nums); % grab the first two [C,D,E] = unique(nums); % grap all three
A =
1 1
B =
4
ans =
1 2 3 4 8 9
When a function takes only string arguments, we can call it using command syntax as in the following examples. Each input is separated by a space.
display hello % command syntax strcat one two three four % four inputs
hello
ans =
onetwothreefour
Creating Functions
To create your own function, open a new file in the editor and begin by creating the function header, which includes the name of the function and its inputs and outputs. When you save the m-file, you must give it exactly the same name as the function name in the header. You cannot create functions within script files, (except for anonymous functions discussed below). Make sure that the file location is on the Matlab search path, (see the section below).
function [output1 ,output2, output3] = myfunction(input1, input2)
Comments, denoted by percent signs, can occur anywhere in the file, however, only comments directly below the function header, (with no spaces in between) are included in the auto generated help entry. Only the first line of comments is searched in calls to lookfor. You can start and end a block of comments with the characters {% and %}.
%{ Block Comments %}
Within the function, you can use the inputs as local variables and you must assign values to each of the outputs before the function terminates, (at least those that will be assigned by the caller of the function). It is customary to end the function with the end keyword but this is optional unless you have nested functions or multiple functions per file as described below.
Here is an example of a simple function. It must be saved in a file called quadform.m.
function [X1,X2] = quadform(A,B,C) % Implementation of the quadratic formula. tmp = sqrt(B.^2 - 4*A*C); X1 = (-B + tmp)./(2*A); X2 = (-B - tmp)./(2*A); end
Multiple Functions Per File
You can have multiple functions per file but only the function whose name corresponds to the filename is accessible from outside the file. The other functions can be used, however, from within this main function just as they would be if they were saved elsewhere. Each function must end with the end keyword.
Nesting Functions
Relatively new to Matlab is the ability to nest functions within each other. This can be extremely useful. Nested functions operate much like the multiple-functions-per-file case above but are included before the final end statement of the main function. The principal difference is that they share their lexical scope with their parent so that variables created within the parent function are accessible in the nested function and vice versa. You can nest functions within functions, within functions as deep as you like, although more than one level is rarely necessary. Nested functions are not accessible outside of the top level function.
function C = myMainFunction(input1, input2) M = 22; K = innerFunction(3,2) + 1; C = K + 2; function B = innerFunction(D,E) Z = D + E - input1 - input2; B = Z + M; end end
Nested functions can call other nested functions at the same level, (i.e. both contained within the same parent function), however this can sometimes obfuscate the flow of control in your program, making it difficult to read and debug, so do so with caution.
In general, however, using nested functions can make your code easier read, (and write) as you can break larger computations into smaller chunks and the name you give each inner function acts to self document its action. This is of course the same benefit you would enjoy by writing multiple functions and saving them in separate files, but it is often easier to organize your program when all of the code is within one file. Since nested functions share their lexical scope, they are very tightly coupled with the parent function. If you find yourself writing a nested function that would be useful elsewhere, not just in the current program, consider saving it as its own stand alone function.
It is often useful to parameterize nested functions even though they could just access the variables from the parent function directly. Parameterization lets you call the same nested function many times with different inputs each time. It can also make your code more readable and extensible.
Recursive Functions
Like any programming language worth its salt, Matlab supports recursive functions, that is, functions who call themselves.
function n = countNodes(tree) if(isempty(tree)) n = 0; else n = countNodes(tree.left) + countNodes(tree.right) + 1 end end
Many recursive algorithms require that you initialize certain variables before you execute the recursive loop. Nesting the recursive functions can be very handy in these cases.
Keep in mind, however, that recursive function calls in Matlab are no faster and may be slower than using loops, which are themselves quite slow. See the section on vectorization in the flowOfControl chapter.
Function Handles / Anonymous Functions
We can pass functions as inputs to other functions in Matlab by first creating a handle to the function and then passing the handle as you would any other variable. Doing so can allow you write generic code in which you predefine the circumstances under which you want a function to execute but not the precise actions that are to occur when it does; this is left up to the passed function itself. Perhaps you have code, like the above countNodes above, which iterates over every node in a tree. You could parameterize this core function so that the action performed at each node is governed by the specified function and not hard coded.
We can create handles to existing functions but can also create functions ‘on the fly’. These are called anonymous or inline functions.
To create a handle to function, we use the @ symbol followed by the name of the function, in what is essentially lambda notation. We can also optionally define the input variables following @, in parentheses. We begin by creating a handle to the exponential function and demonstrate how to use it. In the second case, we create a composition of existing functions and specify the input variables. We can create handles to our own functions as well, (even nested functions) in the same way.
h = @exp % h is now a handle to exp h(2) % evaluate h(2) = exp(2)
h =
@exp
ans =
7.3891
g = @(x,y)sqrt(exp(x).*y.^sin(x))+x.*y % create a more complicated inline function g(3,5) % evaluate g
g =
@(x,y)sqrt(exp(x).*y.^sin(x))+x.*y
ans =
20.0207
As an alternative to using function handles, we can pass the string names of functions and either convert to handles using the str2func() function or evaluate them using the feval() function. The eval() function lets you execute any string as if it were typed at the command prompt.
s = str2func(’sin’)
s(0)
feval(‘cos’,pi)
eval(‘E = 3′)
s =
@sin
ans =
0
ans =
-1
E =
3
Function Arithmetic
It can often be useful to compose two or more functions together to create a new function.
f = @(x) 2*x.^2; % start with functions f, g g = @(x,y) log(x.*y); h = @(x,y) f(x) + 2*g(x,f(y))-f(g(x,y)).*g(2,y);% create a new function, h, from f and g.
Here is a concise way to create a 100 degree polynomial.
f = @(x)0; % start with the constant function for i=1:100 f = @(x)f(x) + x.^i; % keep adding higher order terms. end
Currying
Currying named after Haskel Curry. Is essentially a way of transforming a function of n variables into a function of m < n variables by specifying values for the remaining inputs. If we have a function that takes in a large number of inputs, which we will call over and over, and most of those inputs will remain the same through subsequent calls, currying can be very useful.
Create some horrendous function.
f = @(a,b,c,d,e,f,g,h,i,j,k) a*b+c-d/e-f*g.^h-i/j*k;
Suppose a through h will have fixed values for many calls. We can create a new function from the old by setting some of its values.
fcurry = @(i,j,k)f(2,4,2,0,1,2,3,2,i,j,k); test = isequal(f(2,4,2,0,1,2,3,2,9,9,9),fcurry(9,9,9))
test =
1
This same technique can be useful even when the functions are not mathematical in nature but simply take a lot of parameters, (like many of the plot commands).
Variable # of Input Arguments
Matlab supports functions with a variable number of input arguments, allowing the user to to decide how many to pass in, depending on the context. There are two approaches we can take, (or a combination of the two.
- Create the function with the maximum number of possible input arguments and then check how many inputs were provided by the user with the nargin() function. The remaining inputs can then be assigned default values.
- Use the varargin construct, which ‘absorbs’ all the inputs that come its way. It must occur last in the series of inputs as in the following: function myfunc(A, B, varargin) . If the user provides 2 inputs here, varargin , (a cell array) is empty, whereas if say 10 inputs are provided, varargin will hold the remaining 8. The entries in varargin can be accessed via varargin{1} , varargin{2} , etc, with curly braces. See the section on cell arrays for more information. The narargin() function can still be used here and returns the number of inputs the user specified, (not necessarily 2 or 3).
First Approach
result = myfunc(1,2) % user calls function with 2 inputs function E = myfunc(A,B,C,D) if(nargin < 4) ,D = 1,end if(nargin < 3) ,C = 2,end if(nargin < 2) ,B = 3,end if(nargin == 0),A = 4,end E = A + B + C + D; end
Following the call, result will be 6 = 1+2+2+1.
Second Approach
result = mysum(1,2,3,6,2,9,7) function E = mysum(varargin) E = 0; for i=1:nargin E = E + varargin{i}; end end
Following this call, result will be 30 = 1+2+3+6+2+9+7
process_options
While a variable number of input arguments can be very useful, a major downside is that the order in which the inputs must be specified is fixed. A better method is to use the process_options() function written by Mark Paskin, which allows us to easily parse named parameters so that users can specify inputs in any order they like. With this approach, the values for the inputs are preceded by their names when the function is called.
A = myfunc(‘C’,2, ‘A’,3, ‘B’,1, ‘D’,5)
Inside the function, we then pass varargin to the process_options function, specify the names we are expecting, and default values should an input not be provided. Here is an example code snippet.
function myfunc(varargin) [A,B,C,D,E] = process_options(varargin,'A',3,'B',1,'C',2,'D',5,'E',9);
See the included placeFigures() function for a longer example.
process_opttions() is available here http://www.cs.ubc.ca/~murphyk/Software/matlab/process_options.m
Redirecting Variable Inputs
Suppose you obtain a number of arguments via varargin and want to pass some or all of them directly to another function without having to parse them first. Since varargin is a cell array, we can index into it with multiple indices at once, (or all, using the : operator) and redirect the multiple return values straight into the parameter list of another function. This is equivalent to entering each entry one at a time into the parameter list, separated by commas as you would normally do.
Suppose for instance, that we call mainFunction below with 5 arguments. We can redirect these five arguments to secondFunction() , which expects 5 inputs, and the last 3 to thirdFunction() , which expects 3 inputs. You can perform this same trick with any cell array, not just varargin.
result = mainFunction(1,2,3,4,5); function d = mainFunction(varargin) a = varargin{1}; b = varargin{2}; c = otherFunction(varargin{:}); d = thridFunction(varargin{2:end}) + a + b + c; end function f = secondFunction(a,b,c,d,e) f = a+b-c*d/e; end function g = thirdFunction(h,i,j) g = h*i-j; end
Variable # of Output Arguments
Matlab also supports variable number of output arguments using varargout() , although this is fairly uncommon. Type doc varargout for more information. The nargout() function is more useful, returning the number of outputs the caller of the function has asked for. Suppose, for instance, a function normally returns 3 outputs but all three take a long time to compute. If nargout() indicates that the user only asked for one output as in A = myfunc(2,4) as opposed to [A,B,C] = myfunc(2,4) we can bypass the expensive computation of B and C. Recall that Matlab only complains about undeclared variables when an attempt to access them is made, not before, and so this works perfectly fine. The built in Matlab hist() function operates this way. A histogram is only graphed if no outputs are specified, as in hist(data), otherwise, just the bin counts are returned.
Matlab Path and Search Order
Matlab finds the functions you call by searching the Matlab Path in the order in which the directories on the path are specified. Subdirectories of included directories are not by default added. The easiest way to add new directories or view the existing path is to use the graphical pathtool available via file->set path or by typing pathtool at the command prompt. There are many other functions related to path control, shown below. When multiple files with the same name exist on the Matlab path, Matlab silently executes the one higher up on the path. You can check which version will be executed with the which() command.
which exp % which implementation will be used
built-in (C:\Program Files\MATLAB\R2008a\toolbox\matlab\elfun\@double\exp) % double method
which -all exp; % names of all implementations allfiles = what; % list all of the m-files in the current directory exist('writingFunctions','file'); % check if the specified file exists
built-in (C:\Program Files\MATLAB\R2008a\toolbox\matlab\elfun\@double\exp) % double method
built-in (C:\Program Files\MATLAB\R2008a\toolbox\matlab\elfun\@single\exp) % Shadowed single method
C:\Program Files\MATLAB\R2008a\toolbox\control\control\@lti\exp.m % Shadowed lti method
C:\Program Files\MATLAB\R2008a\toolbox\distcomp\parallel\elfun\@distributed\exp.m % Shadowed distributed method
C:\Program Files\MATLAB\R2008a\toolbox\finance\ftseries\@fints\exp.m % Shadowed fints method
C:\Program Files\MATLAB\R2008a\toolbox\mbc\mbcmodels\@xregcovariance\exp.m % Shadowed xregcovariance method
C:\Program Files\MATLAB\R2008a\toolbox\symbolic\@sym\exp.m % Shadowed sym method
pathtool; % launch the path tool addpath('c:\windows\temp'); % add this directory to the path save = userpath % display,(or change) default save directory mroot = matlabroot % display the root Matlab directory
save =
C:\Users\matt\Documents\MATLAB;
mroot =
C:\Program Files\MATLAB\R2008a
We can use the genpath() function to build a string containing the specified directory name and all of its subdirectories formed via recursive descent. We can then pass this string into addpath() for instance.
source = ‘c:\Windows\temp’;
d = genpath(source);
Here are a few related functions.
sfile = [source,'tmp.txt']; [pathstr, name, ext, versn] = fileparts(sfile) % parse a filename f = fullfile('c:','windows','temp','myfile.tmp')% create a file path from parts sep = filesep % get the file separator for this OS dinfo = dir; % get a struct holding directory info.
pathstr =
c:\Windows
name =
temptmp
ext =
.txt
versn =
''
f =
c:\windows\temp\myfile.tmp
sep =
\
Private Functions & Packages
We will say more about private functions and packages in the object oriented programming chapter, however, they can be used in non-OO code as well. Any functions you save into a directory named private will only be accessible by functions in the containing directory one level up, (or the private directory itself). Thus, you can create functions with common names like sum or display, put them into a private directory and you will not interfere with existing implementations outside of your project.
Matlab, (as of 2008a), also supports packages, which can be used to partition the name space. Packages are directories beginning with the ‘+’ symbol. Any functions you place into these directories are then only accessible by first referring to the package name. Suppose I create a directory called ‘+lab’ and put the function ‘calc’ into this directory. I would then call it with the syntax lab.calc() . Packages can provide an easy way to organize your code and like private directories, let you reuse common function names. You can temporarily import a package, (meaning you do not have to use the . syntax) with the import command, i.e. by calling say import lab .
clear all;
Popularity: 1% [?]

















































