I need to generate multiple results but one at a time, as opposed to everything at once in an array.
How do I do that in Matlab with a generator like syntax as in Python?
The yield keyword in Python is less known but has a greater utility. we will see the yield python example. The Yield keyword in Python is similar to a return statement used for returning values in Python which returns a generator object to the one who calls the function which contains yield, instead of simply returning a value.
Below are some differences between yield and return in Python. When the caller calls the generator function, it packs all the return values from yield into a generator object and returned. Also, the code execution starts only when the caller iterates over the object.
But as an exercise to understand what is going on, try to use continuation passing style to implement generator objects without use of the yield keyword. Here is an example in plain language. I will provide a correspondence between high-level human concepts to low-level Python concepts.
Instead of return values using yield, you can also call functions. For example, suppose you have a function called cubes which takes an input number and cubes it, and there exists another function that uses a yield statement to generate cubes of a range of numbers.
When executing functions that use the yield
keyword, they actually return a generator. Generators are a type of iterators. While MATLAB does not provide the syntax for either, you can implement the "iterator interface" yourself. Here is an example similar to xrange
function in python:
classdef rangeIterator < handle
properties (Access = private)
i
n
end
methods
function obj = rangeIterator(n)
obj.i = 0;
obj.n = n;
end
function val = next(obj)
if obj.i < obj.n
val = obj.i;
obj.i = obj.i + 1;
else
error('Iterator:StopIteration', 'Stop iteration')
end
end
function reset(obj)
obj.i = 0;
end
end
end
Here is how we use the iterator:
r = rangeIterator(10);
try
% keep call next() method until it throws StopIteration
while true
x = r.next();
disp(x);
end
catch ME
% if it is not the "stop iteration" exception, rethrow it as an error
if ~strcmp(ME.identifier,'Iterator:StopIteration')
rethrow(ME);
end
end
Note the when using the construct for .. in ..
in Python on iterators, it internally does a similar thing.
You could write something similar using regular functions instead of classes, by using either persistent
variables or a closure to store the local state of the function, and return "intermediate results" each time it is called.
In MATLAB (not yet? in Octave), you can use closures (nested, scoped functions):
function iterator = MyTimeStampedValues(values)
index = 1;
function [value, timestamp, done] = next()
if index <= length(values)
value = values(index);
timestamp = datestr(now);
done = (index == length(values));
index = index + 1;
else
error('Values exhausted');
end
end
iterator = @next;
end
and then
iterator = MyTimeStampedValues([1 2 3 4 5]);
[v, ts, done] = iterator(); % [1, '13-Jan-2014 23:30:45', false]
[v, ts, done] = iterator(); % ...
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