In a generic function definition
function [ <outarg1>, <outarg2>, ... <outargn> ] = <function name>(<inarg1>, ...)
the <outargi>
are the output arguments, or outargs.
In the function body treat all of the outargs as local variables that can be used exactly like any other Matlab variables. Local means the same thing that it did in Maple, i.e. that only the function knows about the existence of its local variables and they will not conflict with variables with the same names that are used in other functions or scripts. with variable
Ensure that each and every outarg has a value assigned to it before the function
returns, which will happen either when execution reaches the end of the function
definition is reached, or when an explicit return
statement is encountered.
That is, each and every outarg must appear on the left hand side of at least one assignment statement.
Nothing stops you from reassigning the outarg one or more times in the function body so that it appears on the LHS of more than one assignment statement, but it must be assigned at least once, or the function definition is incorrect.
This is an extremely important concept that you must master. It can be tricky, especially if you are relatively new to programming and especially since you have done some Maple programming and thus may be apt to program a Matlab function in the same way you code a Maple procedure.
First, bear in mind that the mechanism by which functions return values is different in the two languages and you must understand the difference, and more generally, precisely how we make Matlab functions return values, where I remind you that in this context return means give back to the environment, in precisely the same sense as if I view \(\sin(x)\) as a machine or black-box, when I give it the input \(\pi/4\), it returns \(\sqrt{2}/2\).
Second, as was the case in Maple, it is of fundamental importance for you to understand the distinction between the following:
A key reason that this is a confusing issue is that Matlab (like Maple) routinely produces output to the command window that "echoes" the effect of every statement that is executed.
Specifically, as we have seen, the basic interaction cycle with Matlab goes as follows (this isn't complete, but it illustrates the central point):
We type an expression---a Matlab statement---that Matlab can evaluate, such as
>> pi
or
>> 1:5
or
>> x = 42
Provided that the output is not suppressed by a semi-colon terminator, Matlab will show us what happened, always in the form of an assignment statement.
So we see
ans = 3.1416
or
ans = 1 2 3 4 5
or
x = 42
where I have suppressed the newlines that Matlab adds after the = sign.
We type another statement, and the cycle goes on.
As an aside, if what we've typed isn't an explicit assignment statement (e.g.
cases 1 and 2 above) the Matlab
always assigns the value of the expression to the special variable ans
as a matter of convenience. If we want to save (temporarily) the value of
some calculation but don't want to invent the name of a variable to save it in,
then it is convenient for it to get stuffed into a default variable whose name
is fairly logical and easy to type. And if we don't particularly
want to save the value, then assigning it to ans
isn't going to hurt.
Consider the following (incorrect) definition of a function
mymax2_bad
that is to return the maximum value of its two input
arguments x
and y
. Particularly if Maple programming
is still fresh in your mind, you might be inclined to write
something like this:
function val = mymax2_bad(x, y)
if x > y
x
else
y
end
end
(This function is included in the course demonstration package
so you should be able to verify that this is the definition
using type mymax2_bad
.)
In Maple this is the correct way to code things since the value of the last expression that is evaluated is the value that is returned by the procedure.
Now let's see what happens when we call the function:
>> mymax2_bad(3, 4)
y =
4
The output---i.e. what appears in the command window after we enter the statement---looks reasonable, especially if we weren't scrutinizing it carefully.
But now let's try to assign what it returns to a variable
>> max34_bad = mymax2_bad(3, 4)
Error in <a href="matlab:helpUtils.errorDocCallback('mymax2_bad', ...
if x > y
Output argument "val" (and maybe others) not assigned during call to ...
where ...
denotes omitted diagnostic information. The mere appearance
of the error message tells us that something is amiss, and the
text of the error message does actually does tell us how to fix the
problem. However, in order to make sense of the message, we
have to understand how values are returned from functions in Matlab.
And the reason that we made the mistake in the first place was that
we didn't understand this. So the message isn't very useful
at this point.
Another aside: before proceeding to a description of a correct implementation of the function, let us note that it is a fact that we will frequently find ourselves in situations like this when learning a computer language, and it certainly isn't unique to that activity. The first time or few times that we run into a particular problem we may have no clue as to what is wrong or what "the computer is telling us" when it spits out some error message. It may take time, sometimes a lot of time, to resolve the issue. But eventually two things tend to happen. First, we tend to make the specific type of mistake less frequently. Second, and more importantly, we learn how to more swiftly diagnose the problem---through understanding what diagnostic messages mean, for example---and how to more swiftly fix it. Ultimately, as with most activities we deem worth mastering, mastery is largely a function of experience.
OK, a correct version of the function is
function val = mymax2_good(x, y)
if x > y
val = x;
else
val = y;
end
end
and there are two differences in the correct code relative to the incorrect implementation:
Each clause of the if
the statement is an assignment
of a value to val
.
This is the crucial difference that makes the second form correct.
The assignment statements are terminated with semicolons, which suppress the normal output.
This is a technical difference, but one that is worth noting since accidentally omitting a terminator at the end of one or more statements in a function can lead to confusing and difficult-to-diagnose behaviour, especially for novices.
When we invoke mymax2_good(3, 4)
and assign the return value,
the correct thing happens:
>> max34_good = mymax2_good(3, 4)
max34_good =
4
Now, if we go back and look at the output from mymax2_bad(3,4)
we can understand what is happening and what makes the coding
of mymax2_bad
incorrect:
>> mymax2_bad(3, 4)
y =
4
In this case the output
y =
4
comes from within the function as it runs, because we neglected to end the statement with a semicolon, and is simply Matlab showing us what happens when the function executes
y
Note that once y
has a value, then y
by itself as a line of
Matlab code is a Matlab statement, even if it doesn't seem
syntactically complicated enough to be one.
Since on entry to the function the mappings
x -> 3
y -> 4
are made,
what appears in the command window as mymax2_bad
executes is precisely what we
see when we type the following interactively in the command window:
>> y = 4;
>> y
y =
4
So although the 4 we see in the output of
mymax2_bad(3, 4)
y =
4
is obviously the same value as the 4 we see in the output of
>> max34_good = mymax2_good(3, 4)
max34_good =
4
there's a fundamental distinction between the two:
In the good invocation, the 4 is the actual value returned by the function. It can be assigned to a variable, which is precisely what we have done with the statement
>> max34_good = mymax2_good(3, 4)
Also, because this statement doesn't end with a semi-colon, the value 4 is also displayed:
max34_good = 4
Let's go one step further to make a final point about the distinction between the good code and the bad code.
If we suppress the output from the good call/assignment
>> max34_good = mymax2_good(3,4);
then max34_good
is still assigned the value 4, but nothing appears
in the command window.
If we suppress the output from bad/call assignment
>> max34_bad = mymax2_bad(3,4);
then we still see
y = 4
before the error message appears.
That output is coming from within the function, has nothing to do with
the assignment of max34_good
at the command prompt and can only be
suppressed by changing the source file mymax2_bad
so that the (incorrect)
statement y
has a semicolon at the end.
y -> y;
So let's now focus on the issue of how we properly code functions in
Matlab by looking at the key elements of the definition of mymax2_good
function val = mymax2_good(x, y)
if x > y
val = x;
else
val = y;
end
end
First we look at the header and simply do some counting and identification:
How many input arguments are there? I.e. how many comma-separated names appear
within the set of parentheses that follows the name of the function, mymax2_good
?
Answer: 2
What are the names of the input arguments?
Answer: x
and y
How many output arguments are there? I.e. how many names appear between the
keyword function
and the name of the function mymax2_good
?
Answer: 1
What is the name of the output argument?
Answer: val
Second, let's note that there are three pieces of code that all look like
assignments to the output argument val
:
function val = mymax2_good(x, y)
and
val = x;
val = y;
The last two are assignment statements---they define (or equivalently, set or change its value.) These are active pieces of code, pieces that do something, pieces that we refer to as executable statements, irrespective of what computer language we are using.
The first statement, however, is not an assignment statement. It is not an executable statement and should be viewed as passive, rather than active. It defines:
mymax2_good
How many input arguments it has: 2, and what their names are: x
and y
.
In generic programming terminology we call these the formal arguments.
The values
or variable names that we supply when we call the function, e.g. 3
and 4
in
>> mymax2_good(3, 4)
or in1
and in2
in
>> in1 = 3;
>> in2 = 4;
>> mymax2_good(in1, in2)
are the actual arguments. Whenever we call the function a mapping is established
between the actual and formal arguments and then everywhere that the name of
a formal argument (x
for example) appears in the body of the function, the
value of the actual argument (3 for example) is used.
How many output arguments it has: 1, and
what its name is: val
FINALLY!!
QUESTION:
How do we make Matlab functions return values?
ANSWER
Treat every output argument as a variable that is local to the function, and make sure that it has been assigned a value before the function return.
CORRECT IMPLEMENTATION
In our example
function val = mymax2_good(x, y)
if x > y
val = x;
else
val = y;
end
% function returns at this point
end
The output argument, val
, is assigned a value no matter which clause of the
if
executes.
Thus, when execution reaches the point where the function
returns---in this case where the function definition ends as indicated by
the comment that I've added, val
has been assigned and the function returns
the correct value.
Note that we can view the assignment of the return value from a function to a variable, as in
>> q = mymax2_good(3, 4)
as another mapping. In this interpretation mymax2_good(3, 4)
will ultimately
be mapped to (replaced by) the value that val
has when the function returns.
INCORRECT IMPLEMENTATION
In contrast
function val = mymax2_bad(x, y)
if x > y
x
else
y
end
end
contains no assignments to val
, and is thus fundamentally incorrect. When
we use it ...
>> max34 = mymax2_bad(3, 4)
... the error message from Matlab tells us what is wrong:
Output argument "val" (and maybe others) not assigned during call to ...
For some of you, all of this will seem obvious, in which case it is highly unlikely that you read this far. For the rest of you, if the picture still isn't clear, or doesn't become clear after you've written a couple of functions, ask for help!