# # MATLAB Best Practices

## # Indent code properly

Proper indentation gives not only the aesthetic look but also increases the readability of the code.

For example, consider the following code:

``````%no need to understand the code, just give it a look
n = 2;
bf = false;
while n>1
for ii = 1:n
for jj = 1:n
if ii+jj>30
bf = true;
break
end
end
if bf
break
end
end
if bf
break
end
n = n + 1;
end

``````

As you can see, you need to give a careful look to see which loop and `if` statements are ending where.
With smart indentation, you'll get this look:

``````n = 2;
bf = false;
while n>1
for ii = 1:n
for jj = 1:n
if ii+jj>30
bf = true;
break
end
end
if bf
break
end
end
if bf
break
end
n = n + 1;
end

``````

This clearly indicates the starting and ending of loops/`if` statement.

You can do smart indentation by:
selecting all your code (Ctrl+A)
and then pressing Ctrl+I or clicking (opens new window) from edit bar. (opens new window)

## # Keep lines short

Use the continuation character (ellipsis) `...` to continue long statement.

Example:

``````MyFunc( parameter1,parameter2,parameter3,parameter4, parameter5, parameter6,parameter7, parameter8, parameter9)

``````

can be replaced by:

``````MyFunc( parameter1, ...
parameter2, ...
parameter3, ...
parameter4, ...
parameter5, ...
parameter6, ...
parameter7, ...
parameter8, ...
parameter9)

``````

## # Use assert

Matlab allows some very trivial mistakes to go by silently, which might cause an error to be raised much later in the run - making debugging hard. If you assume something about your variables, validate it.

``````function out1 = get_cell_value_at_index(scalar1,cell2)
assert(isscalar(scalar1),'1st input must be a scalar')
assert(iscell(cell2),'2nd input must be a cell array')

assert(numel(cell2) >= scalar1),'2nd input must have more elements than the value of the 1st input')
assert(~isempty(cell2{scalar1}),'2nd input at location is empty')

out1 = cell2{scalar1};

``````

## # Avoid loops

Most of the time, loops are computationally expensive with Matlab. Your code will be orders of magnitudes faster if you use vectorization. It also often makes your code more modular, easily modifiable, and easier to debug. The major downside is that you have to take time to plan the data structures, and dimension errors are easier to come by.

### # Examples

Don't write

``````for t=0:0.1:2*pi
R(end+1)=cos(t);
end

``````

but

``````t=0:0.1:2*pi;
R=cos(t)

``````

Don't write

``````for i=1:n
for j=1:m
c(i,j)=a(i)+2*b(j);
end
end

``````

But something similar to

``````c=repmat(a.',1,m)+2*repmat(b,n,1)

``````

For more details, see vectorization (opens new window)

## # Block Comment Operator

It is a good practice to add comments that describe the code. It is helpful for others and even for the coder when returned later. A single line can be commented using the `%` symbol or using the shortkey `Ctrl+R`. To uncomment a previously commented line remove the `%` symbol or use shortkey `Crtl+T`.

While commenting a block of code can be done by adding a `%` symbol at the beginning of each line, newer versions of MATLAB (after 2015a) let you use the Block Comment Operator `%{ code %}`. This operator increases the readability of the code. It can be used for both code commenting and function help documentation. The Block can be folded and unfolded to increase the readability of the code. (opens new window)

As it can be seen the `%{` and `%}` operators must appear alone on the lines. Do not include any other text on these lines.

``````function y = myFunction(x)
%{
myFunction  Binary Singleton Expansion Function
y = myFunction(x) applies the element-by-element binary operation
specified by the function handle FUNC to arrays A and B, with implicit
expansion enabled.
%}

%%  Compute z(x, y) = x.*sin(y) on a grid:
% x = 1:10;
y = x.';

%{
z = zeros(numel(x),numel(y));
for ii=1:numel(x)
for jj=1:numel(y)
z(ii,jj) = x(ii)*sin(y(jj));
end
end
%}

z = bsxfun(@(x, y) x.*sin(y), x, y);
y = y + z;

end

``````

## # Create Unique Name for Temporary File

While coding a script or a function, it can be the case that one or more than one temporary file be needed in order to, for example, store some data.

In order to avoid overwriting an existing file or to shadow a MATLAB function the tempname (opens new window) function can be used to generate a unique name for a temporary file in the system temporary folder.

``````my_temp_file=tempname

``````

The filename is generated without the extension; it can be added by concatenating the desired extension to the name generated by `tempname`

``````my_temp_file_with_ext=[tempname '.txt']

``````

The locaton of the system temporary folder can be retrieved by caling the tempdir (opens new window) function.

If, during the execution of the function / script, the temporary file is no longer needed, it can be deleted by using the function delete (opens new window)

Since `delete` does not ask for confirmation, it might be useful to set `on` the option to move the file to be deleted in the `recycle` folder.

This can be done by using the function recycle (opens new window) this way:

``````recycle('on')

``````

In the following example, a possible usage of the functions `tempname`, `delete` and `recycle` is proposed.

``````%
% Create some example data
%
theta=0:.1:2*pi;
x=cos(theta);
y=sin(theta);
%
% Generate the temporary filename
%
my_temp_file=[tempname '.mat'];
%
% Split the filename (path, name, extension) and display them in a message box
[tmp_file_path,tmp_file_name, tmp_file_ext]=fileparts(my_temp_file)
uiwait(msgbox(sprintf('Path= %s\nName= %s\nExt= %s', ...
tmp_file_path,tmp_file_name,tmp_file_ext),'TEMPORARY FILE'))
%
% Save the varaibles in a temporary file
%
save(my_temp_file,'x','y','theta')
%
% Load the varaibles from the temporary file
%
%
% Set the reclycle option on
%
recycle('on')
%
% Delete the temporary file
%
delete(my_temp_file)

``````

Caveat

The temporary filename is generated by using the `java.util.UUID.randomUUID` method (randomUUID (opens new window)).

If MATLAB is run without JVM, the temporary filename is generated by using
`matlab.internal.timing.timing` based on the CPU counter and time. In this case the temporary filename is not guaranteed to be unique.

## # Use validateattributes

The function validateattributes (opens new window) can be used to validate an array against a set of specifications

It can be therefore used to validate the input provided to a function.

In the following example, the function `test_validateattributes` requires three input

`function test_validateattributes(input_1,input_2,input_3)`

The input specification are:

• array_1:
- class: double - size: [3,2] - values: elements must be not NaN

char_array:

• class: char
• value: the string must not be empty

array_3

• class: double
• size: [5 1]
• values: elements must be real

To validate the three input, the function `validateattributes` can be called with the following syntax:

``````validateattributes(A,classes,attributes,funcName,varName,argIndex)

``````

where:

• `A` is the array to be vaidated
• `classes`: is the `type` of the array (e. g. `single`, `double`, `logical`)
• `attributes`: are the atrributes the input array has to match (e. g. `[3,2], size` to specify the size of the array, `nonnan` to specify that the array shall not have NaN values)
• `funcName`: is the name of the function in which the validation occurs. This argument is used in the generation of the error message (if any)
• `varName`: is the name of the array under validation. This argument is used in the generation of the error message (if any)
• `argIndex`: is the position of the inpurt array in the list of input. This argument is used in the generation of the error message (if any)
• In case one or more than one input does not match the specification, an error message is generated.

In case of more than one invalid input, the validation stops when the first mismatch is found.

This is `function test_validateattributes` in which the input validation has been implemented.

Since the function requires three input, a first check on the number of input provided is performed using the fnction nargin (opens new window).

``````function test_validateattributes(array_1,char_array_1,array_3)
%
% Check for the number of expected input: if the number of input is less
% than the require, the function exits with an error message
%
if(nargin ~= 3)
error('Error: TEST_VALIDATEATTRIBUTES requires 3 input, found %d',nargin)
end
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the first input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #1 name (only used in the generation of the error message)
%
input_1_name='array_1';
%
% INPUT #1 position (only used in the generation of the error message)
%
input_1_position=1;
%
% Expected CLASS of the first input MUST BE "double"
%
input_1_class={'double'};
%
% Expected ATTRIBUTES of the first input
%   SIZE: MUST BE [3,2]
%
input_1_size_attribute='size';
input_1_size=[3,2];
%
%   VALUE CHECK: the element MUST BE NOT NaN
%
input_1_value_type='nonnan';
%
% Build the INPUT 1 attributes
%
input_1_attributes={input_1_size_attribute,input_1_size, ...
input_1_value_type};
%
% CHECK THE VALIDITY OF THE FIRST INPUT
%
validateattributes(array_1, ...
input_1_class,input_1_attributes,'', ...
input_1_name,input_1_position);

%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the second input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #1 name (only used in the generation of the error message)
%
input_2_name='char_array_1';
%
% INPUT #2 position (only used in the generation of the error message)
%
input_2_position=2;
%
% Expected CLASS of the first input MUST BE "string"
%
input_2_class={'char'};
%
%   VALUE CHECK: the element must be not NaN
%
input_2_size_attribute='nonempty';
%
% Build the INPUT 2 attributes
%
input_2_attributes={input_2_size_attribute};
%
% CHECK THE VALIDITY OF THE SECOND INPUT
%
validateattributes(char_array_1, ...
input_2_class,input_2_attributes,'', ...
input_2_name,input_2_position);
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the third input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #3 name (only used in the generation of the error message)
%
input_3_name='array_3';
%
% INPUT #3 position (only used in the generation of the error message)
%
input_3_position=3;
%
% Expected CLASS of the first input MUST BE "double"
%
input_3_class={'double'};
%
% Expected ATTRIBUTES of the first input
%   SIZE: must be 
input_3_size_attribute='size';
input_3_size=[5 1];
%   VALUE CHECK: the elements must be real
input_3_value_type='real';
%
% Build the INPUT 3 attributes
%
input_3_attributes={input_3_size_attribute,input_3_size, ...
input_3_value_type};
%
% CHECK THE VALIDITY OF THE FIRST INPUT
%
validateattributes(array_3, ...
input_3_class,input_3_attributes,'', ...
input_3_name,input_3_position);

disp('All the three input are OK')

``````

The following script can be used to test the implementation of the validation procedure.

It generate the three input required and, randomly, it makes them not valid.

``````%
% Generate the first input
%
n_rows=randi([2 3],1);
n_cols=2;
input_1=randi([20 30],n_rows,n_cols);
%
% Generate the second input
%
if(rand > 0.5)
input_2='This is a string';
else
input_2='';
end
%
% Generate the third input
%
input_3=acos(rand(5,1)*1.2);
%
% Call the test_validateattributes function with the above generated input
%
input_1
input_2
input_3
%
test_validateattributes(input_1,input_2,input_3)

``````

These are a couple of examples of wrong input detected by the `validateattributes` function:

Wrong input

``````input_1 =

23    22
26    28

input_2 =

''

input_3 =

0.0000 + 0.4455i
1.2420 + 0.0000i
0.4063 + 0.0000i
1.3424 + 0.0000i
1.2186 + 0.0000i

Error using test_validateattributes (line 44)
Expected input number 1, array_1, to be of size 3x2 when it is actually
size 2x2.

``````

Wrong input

``````input_1 =

22    24
21    25
26    27

input_2 =

This is a string

input_3 =

1.1371 + 0.0000i
0.6528 + 0.0000i
1.0479 + 0.0000i
0.0000 + 0.1435i
0.0316 + 0.0000i

Error using test_validateattributes (line 109)
Expected input number 3, array_3, to be real.

``````

Valid input

``````input_1 =

20    25
25    28
24    23

input_2 =

This is a string

input_3 =

0.9696
1.5279
1.3581
0.5234
0.9665

All the three input are OK

``````

#### # Remarks

This topic displays best practices that the community has learned over time.