So, I'm applying for a job and need to figure out how nested functions work. To be more specific, I would like to know exactly how the following example posted by gnovice works.
The question is:
Given the following function, what will the output be when entering the code below in the command window?
function fcnHandle = counter
value = 0;
function currentValue = increment
value = value+1;
currentValue = value;
end
fcnHandle = @increment;
end
f1 = counter();
f2 = counter();
output = [f1() f1() f2() f1() f2()]; %# WHAT IS IT?!
I'm not applying for a job, and I'm able to figure out the answer to the question. I also find the answer from Mohsen to this question intuitive (find the size of a matrix without calling built-in functions). However, I can't help but hearing Albert Einstein's voice in my head.
I think the documentation was a bit messy, so I would be very happy if someone is able to explain how it works.
This use of nested functions is relevant for memoization (for additional reading see: use nested functions to memoize costly functions), since it exploits parametric function handles which store the value of the parameters at creation.
There are two things you need to notice:
counter()
returns a function handle directly to the nested function
f1 = counter()
f1 =
@counter/increment
The nested function will 'save' the scoped variables. Refer to functions()
for details.
s = functions(f1)
s =
function: 'counter/increment'
type: 'nested'
file: '\\ic.ac.uk\homes\ok1011\MATLAB\counter.m'
workspace: {[1x1 struct]}
with the scoped workspace retaining:
s.workspace{1}
ans =
fcnHandle: @counter/increment
value: 0
Basically, counter()
initializes the value
to zero, and successive calls to @counter/increment
will perform value = value+1;
.
Finally, @counter/increment
is assigned to f1
and all f1()
is doing is @counter/increment()
on the previously initialized value
. Initializing f2 = counter()
, creates another counter with a separate saved workspace
.
Let me try....
Each time the function counter()
its called creates an unique function handle. This function handle is a handle to a function called increment, that takes its own variable value, and increments its by one.
So if called twice, like in the code (f1, f2) each time will return the same function (increment) but different handles. You have the function defined TWICE. And each of them now work independently. As this specific function (increment) relies in a saved internal value for its computation, you can observe how if called as in your code sample, outputs [1 2 1 3 2].
A good way of seing the differences better is to redefine the function as:
function fcnHandle = counter(val)
value = val;
function currentValue = increment
value = value+1;
currentValue = value;
end
fcnHandle = @increment;
end
and calling it like:
>> f1 = counter(0);
>> f2 = counter(1000);
>> output = [f1() f1() f2() f1() f2()] %# WHAT IS IT?
Now, you will see that the output is [1 2 1001 3 1002]
Makes more sense now?
This code is created so it exploits this attribute of function handles (its the same thing, but its copied twice).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With