Back to Main Page

## Adding rules: Logic, flow control and loops

Dr Lincoln Colling

ljc65@cam.ac.uk

http://pbs2.mindsci.net

Lecture 2

# Functions

## Functions

• In addition to storing information in variables me might also want to do things to that information
• To process information we need functions
• Functions take inputs and (usually) produce outputs
• Functions work like mathematical functions, e.g., y = x2

if x = 2 then y =4

• They’re just self-contained bits of code with rules for transforming the information

### Some examples of functions

• At the very start we introduced a couple of functions: they `help` function and the `doc`
• The `help` function takes 1 input (the name of another function) and produced an output (a print out of some information about that function)
``````help sin % get help on the sin() function
help('sin') % same as above but more explicitly``````

``````>> help('sin')
sin    Sine of argument in radians.
sin(X) is the sine of the elements of X.

Reference page for sin
Other functions named sin

>> ``````

### Some more functions…

• Notice that when we called the `help` function we didn’t input a variable for where to put the output. That’s because the output just printed to the `CommandWindow`. The `disp` function in our first script does the same…
• With other functions, we might want to store the output in a variable. The `num2str()` function is like this
``````>> number = 1;
>> string = num2str(1);
>> string

string =

'1'

>> ``````

#### Specifying multiple inputs

• Functions can take any arbitrary number of inputs.
• Inputs are just separated with `,` in between the `(`/`)`
``````>> x = rand(10,1);
>> y = rand(10,1);
>> corr(x,y)

ans =

-0.0341``````

#### Specifying multiple outputs

• Functions can also produce any arbitrary number of outputs
• To specify multiple outputs we put them inside `[`/`]` separated with a space or `,`
``````>> x = [5 6 1 4];
>> [value, index] = min(x);
>> value

value =

1

>> index

index =

3``````

Note: Sometimes you might want your function to do different things depending on how many inputs or outputs it receives. At home explore the `nargin()` and `nargout()` functions. Type `doc nargin` and `doc nargout` to do this

# Understanding our first script… again

`OurFirstScript.m`

``````% A simple script
disp(['Hello ' name '! Pleased to meet you']); % say hello``````
1. A `comment` that tells us what the script does
2. Call to the `input()` function with two inputs—two `string` inputs—and an output
• input 1 is displayed at the `CommandWindow` when the function is run
• input 2 tells the function to store the output as a `string`
• the output is stored in the variable called `name`
3. Call to the `disp()` function with one input—three `string`s joined together

## Why write functions?

• Functions are the most import bits of code you’ll write
• The key to their usefulness is that they’re reusable. That is, me might write 1 function and then re-use it in 100s of different scripts

### Our first function

Lets write a function that works out a mean

``````function meanValue = OurMeanFunc(inputVector)

% return the mean of some inputs

numberOfItems = length(inputVector) % how long is the vector
sumOfItems = sum(inputVector) % add all the numbers together

meanValue = sumOfItems / numberOfItems % work out a mean``````

### Our second function

Lets output a couple more values

``````function [meanValue,minValue,maxValue] = DescStats(inputVector)

% return the mean of some inputs, the minimum value, and the maximum value

numberOfItems = length(inputVector) % how long is the vector
sumOfItems = sum(inputVector) % add all the numbers together

meanValue = sumOfItems / numberOfItems % work out a mean
minValue = min(inputVector) % get the minimum value
maxValue = max(inputVector) % get the maximum value``````

## Variable scope

• All variables have a `scope`
• Variables are only available within their scope
• Variables used within a script are available to any script that is run after it
• Variable used within a function are only available within that function

### Scope in scripts

`Script1.m`

``````A = 1; % set A to 1
B = 2; % set B to 2
C = A + B; % Add A and B and store it as C``````

`Script2.m`

``dips(num2str(C * 2)) % multiply C x 2, convert to string and display``

If we run `Script1` and then `Script2` we’ll see ‘4’ printed out

### Scope in functions

`Function1.m`
``````function [] = Function1()
% This function takes no inputs and produces no output
% But it contains the same code as Script1.m

A = 1;
B = 2;
C = A + B;``````
• None of the variables used in the function are available anywhere else other than inside `Function1`
• To access them we must set them as outputs
• Running `Function1` and then `Script2` will produce an error

Note: You can explicitly ask `Matlab` to make some variables available everywhere. You can do this using the `global` command. But often there are better ways to reuse common variables between functions (e.g., by organising commonly used variables in a `structure` that is defined as an `input` and `output` for all functions in a set of related functions). Using `global` can often lead to problems so its best to avoid it if possible.

## Logic

• The core of many programs can be broken down into a series of `yes`/`no` or `true`/`false` questions
• Matlab has a few different ways of asking `true`/`false` questions depending on the data type (e.g., numbers, letters) you’re dealing with
• The operators `==`, `~=`, `>`, `<`, `<=`, and `>=` for `integer`s and `double`s
• The functions `strcmp()` and `strcmpi()` for `string`
• The `ismember()` function for `cell` arrays

### Logic with numbers

The simplest question we can ask is whether two variables are equal. For this we use `==`
``````aNumber = 89 % set aNumber to 89
bNumber = aNumber % set bNumber to the same as aNumber
aNumber == bNumber % returns 1 or TRUE

bNumber = aNumber - 1 % change bNumber to 1 less than aNumber
aNumber == bNumber % returns 0 or FALSE``````
But we can also ask slightly more complex questions
``````aNumber > bNumber % returns 1 or TRUE
aNumber < bNumber % return 0 or FALSE

aNumber ~= bNumber % returns 1 or TRUE``````

### Logic with vectors

In the previous examples we just used single numbers but we can do the same on a `vector` of number
``````aVector = [1 5 6 8 0]
aVector >= 5 % returns: [0 1 1 1 0]``````
We can use the output as a filter
``````% return all the values in aVector that are greater than or equal to 5
aVector(aVector >= 5) % returns: [5 6 8]

% return the locations of the values in aVector that are greater than or equal to 5
find(aVector >= 5) % returns: [2 3 4]``````

### Logical operators

• Sometimes we might want to string together several questions. To do this we can use logical operators
• `&&` means AND
• `||` means OR
• `~` means NOT

### Testing multiple conditions

``````% set some values
x = 10; y = 5;

(x > 1) && (y > 1) % returns 1
(x > 1) && (y < 1) % returns 0

(x < 6) || (y < 6) % returns 1

(x > 0) % returns 1
~(x > 0) % returns 0``````

## Comparing strings

• `string`s work a little differently to comparing numbers
• instead of `==` you use either the `strcmp()` or `strcmpi()` functions
``````aString = 'Lincoln'
bString = 'John'

% aString == bString would returns an error
strcmp(aString,bString) % returns 0

bString = 'lincoln'
strcmp(aString,bString) % returns 0

strcmpi(aString,bString) % ignore case, returns 1``````

# Flow control

• Flow control allows your code to take different paths depending whether certain conditions are met
• Their basic form can be thought of as `IF A THEN B` rules
• In `Matlab` we use the `if` statement
``````birthyear = 1998
if birthyear <  1999
disp('You are old enough to buy beer')
end % notice that we put end when we've finished the rule``````

• You can also use `else` to specify what to do if the condition isn’t met
• You can use any conditional that can return a `TRUE` or a `FALSE`
``````if birthyear < 1999
disp('You are old enough to buy beer')
else
disp('You are not old enough to buy beer!')
end``````
``````if birthyear < 1999
disp('You are old enough to buy beer')
elseif birthyear == 2000
disp('You might be old enough to buy beer')
else
disp('You are not old enough to buy beer!)
end``````
``````% some examples of conditionals you can use
x < n
x > n && b == y
strcmp(aString,'name')``````

## Nested `if` statements

• You can also nest `if` statements inside other `if` statements for more complex flow control
• But be careful, because it can get difficult to read, so it might be better to break down the problem into a set of functions
``````if a == 5
if x < 10
%do something
elseif x > 10
%do something else
end
end``````

## switch and case

• When you have many conditions that need to be checked you can string together several `if`, `elseif`, and `else` statements or you can use `switch` and `case`
``````n = 10 % set n to a number

switch n
case 1
disp('one')
case 2
disp('two')
otherwise
disp('I can only count to two')
end``````

• `switch` and `case` also works with strings the same way they work with numbers
``````n = 'one'

switch n
case 'one'
disp('1')
case 'two'
disp('2')
case {'three','four'}
disp('more than 2 less than 5')
end``````

# Loops

• Sometimes you might want to run a bit of code many times
• For example, you might want to apply a function to a series of numbers
• Or some code that presents a stimulus and collects responses for n trials
• Do to this, we can use a loop. And we can use different types of loops depending on the nature of our problem.

## The for loop

• The simplest type of loop is the `for` loop
• If we pass a range of values (e.g., a `vector` or `cell` array) to a `for` statement then one value of that range will be available on each iteration of the loop
``````for i = 1 : 10
disp(num2str(i))
end``````
``````for n = {'one','two','three'}
disp(n)
end``````

## The while loop

• `for` loops loop over some series of values
• `while` loops, other the hand, loop continuously until some condition is met
``````x = 1
y = 0
while y < 100
y = x^2
disp(['x squared is ' num2str(y)])
x = x + 1
end ``````
``````while ~feof(fid)
fgetl(fid)
end``````

## Vectorising code

• An alternative you using a loop is to pass a range of values to a function and get a range of values back
``````y = []
for x = 1 : 5
y(x) = log10(x)
end``````
``````x = 1:5
y = log10(x)``````

## The cellfun/arrayfun approach

``````y = 1 : 5
arrayfun(@(x) log(x),y)

y = {'1','2','3','4','5'}
cellfun(@(x) str2num(x), y)

y = {'a','1','2','3','4','5'}
cellfun(@(x) str2num(x), y) ``````
``````function y = word2number(x)
switch x
case 'one'
y = 1
case 'two'
y = 2
otherwise
y = 'I can not count that high'
end``````
``````y = {'one','two','three'}
cellfun(@(x) word2number(x), y) % produces an error because the output is a mix of numbers and strings

cellfun(@(x) word2number(x), y,'UniformOutput',false) % tell matlab that the output won't be uniform and that it must package each output in a cell instead of outputting a vector``````