Function with different return variables - matlab

Is there a way to have one function that can return two different variables, but only one at a time AND knowing which one is returned in the function call?
example:
I have the following function in which only one of the outputs is valid (the other one would be [])
function [a,b] = AlternatingOutput (input)
if input == 1
return ONLY A
else
return ONLY B
end
end
and i call it in a script
[a,b] = AlternatingOutput (input)
i want a way to say the following (pseudocode):
if (function outputs a)
[a,~] = AlternatingOutput(input)
elseif (function outputs b)
[~,b] = AlternatingOutput(input)
end
the script is run in a loop, and later i need the newest Valid values for a and b, so i cannot overwrite one of the two with []
I do understand that I could just write a function that checks which variable will be output, but I was wondering if there is a more elegant way.
I hope I have made my question clear, and I hope someone can answer me :)

There is no way to tell if an output argument is actually used. You may check the number of output arguments using nargout and it would allow to distinguish between [a] = AlternatingOutput(input) and [~,b] = AlternatingOutput(input)
I don't know the full context of your problem, but maybe you can put all your variables into a struct? Simply pass this struct everytime you call the function and let it decide which variables to manipulate. (This might be slow in some programming languages, but not in matlab).

How about retuning a cell?
function [ ab ] = testfun( input )
if input
ab={'ax'};
else
ab={2};
end
end
No worries about what is in the cell.
thb you could return what ever you want, Matlab does not check the type anyways

If only one of the outputs from the function AlternatingOutput is valid, then you only need to return one output:
function [X] = AlternatingOutput(input)
if input == 1
X = A;
else
X = B;
end
end
To allocate the retured value to either a or b in the loop, put them into a cell:
C = {AlternatingOutput(1), AlternatingOutput(2)};
and then use input to determine which value is change. If input is either 1 or 2 you can just do
for counter = ...
input = mod(input,2)+1;
C{input}=AlternatingOutput(input);
end

If your function doesn't mind accepting more input variables, why not pass a and b as input:
function [a,b] = AlternatingOutput(a,b,input)
if input == 1
a = new_value_for_a;
% b retains its former value
else
% a retains its former value
b = new_value_for_b;
end
end
Then it can be easily called from your script in a loop:
for i= ...
[a,b] = AlternatingOutput(a,b,input);
...
...
end

Related

Make the basis of a function from nest loop outer components

I have a segment of code where a composition of nested loops needs to be run at various times; however, each time the operations within the nested loops are different. Is there a way to make the outer portion (loop composition) somehow a functional piece, so that the internal operations are variable. For example, below, two code blocks are shown which both use the same loop introduction, but have different purposes. According to the principle of DRY, how can I improve this, so as not to need to repeat myself each time a similar loop needs to be used?
% BLOCK 1
for a = 0:max(aVec)
for p = find(aVec'==a)
iDval = iDauVec{p};
switch numel(iDval)
case 2
r = rEqVec(iDval);
qVec(iDval(1)) = qVec(p) * (r(2)^0.5 / (r(1)^0.5 + r(2)^0.5));
qVec(iDval(2)) = qVec(p) - qVec(iDval(1));
case 1
qVec(iDval) = qVec(p);
end
end
end
% BLOCK 2
for gen = 0:max(genVec)-1
for p = find(genVec'==gen)
iDval = iDauVec{p};
QinitVec(iDval) = QinitVec(p)/numel(iDval);
end
end
You can write your loop structure as a function, which takes a function handle as one of its inputs. Within the loop structure, you can call this function to carry out your operation.
It looks as if the code inside the loop needs the values of p and iDval, and needs to assign to different elements of a vector variable in the workspace. In that case a suitable function definition might be something like this:
function vec = applyFunctionInLoop(aVec, vec, iDauVec, funcToApply)
for a = 0:max(aVec)
for p = find(aVec'==a)
iDval = iDauVec{p};
vec = funcToApply(vec, iDval, p);
end
end
end
You would need to put the code for each different operation you want to carry out in this way into a function with suitable input and output arguments:
function qvec = myFunc1(qVec, iDval, p)
switch numel(iDval)
case 2
r = rEqVec(iDval); % see note
qVec(iDval(1)) = qVec(p) * (r(2)^0.5 / (r(1)^0.5 + r(2)^0.5));
qVec(iDval(2)) = qVec(p) - qVec(iDval(1));
case 1
qVec(iDval) = qVec(p);
end
end
function v = myFunc2(v, ix, q)
v(ix) = v(q)/numel(ix);
end
Now you can use your loop structure to apply each function:
qvec = applyFunctionInLoop(aVec, qVec, iDauVec, myFunc1);
QinitVec = applyFunctionInLoop(aVec, QinitVec, iDauVec, myFunc2);
and so on.
In most of the answer I've kept to the same variable names you used in your question, but in the definition of myFunc2 I've changed the names to emphasise that these variables are local to the function definition - the function is not operating on the variables you passed in to it, but on the values of those variables, which is why we have to pass the final value of the vector out again.
Note that if you want to use the values of other variables in your functions, such as rEqVec in myFunc1, you need to think about whether those variables will be available in the function's workspace. I recommend reading these help pages on the Mathworks site:
Share Data Between Workspaces
Dynamic Function Creation with Anonymous and Nested Functions

MatLab function, variable output

function [ muln, varargout ] = my_mul( varargin )
%MY_MUL This function is used to multiply numbers.
% My_mul function multiplies array of entered numbers, and outputs single
% solution.
% For example: my_mul(12, 2, 3, 5) gives ans = 360
if nargout >=1
disp('Error, wrong number of output arguments');
varargout{1} = 0;
return
end
if nargin <= 1
disp('Error, small number of input argumnets');
return
else
muln = 1;
for i = 1:nargin
muln = muln*varargin{i};
end
end
end
Hi, everyone, I'm just doing my assignment for uni and have a qiuck question.
How can I make this function to give an error if it is called with more than one output.(It meant to give only one) Thanks!
In your function definition, you have defined your function to allow for an unlimited number of outputs. The keyword varargout is a place-holder for a variable number of outputs.
As you have stated in your question, you only want one possible output which in your case looks to be muln. So if you simply remove varargout from your function definition, MATLAB should automatically throw an error if too many outputs are requested
function muln = my_mul(varargin)
If you ever do need to use varargout but want to place constraints on how many outputs are provided for any given scenario, you can check the number of output arguments that were requested using nargout and then throw an error with the error function.
if nargout > 4
error('my_mul:TooManyOutputs', 'Too many outputs requested');
end
My opinion is that if a return value is expected the function needs to throw. Otherwise the caller (function calling this function) will expect everything to be ok. Note that disp('Error') gives information to the developer, but it does not give the program any indication on what happens. More importantly, the information does not give any indication of where the error occurs. This can force the developer to do heavy debugging just to find the error, which is completely unnecessary.
The use of variable output arguments should only be used in case a different number of output arguments should be expected. An example is some customized plot function
function varargout = myplot(varargin)
filename = '';
idx = find(strcmp(varargin,'filename'));
if (~isempty(idx) && length(varargin)<idx+1 && ~ischar(varargin{idx+1}))
error('filename property must be followed by a directory');
elseif(~isempty(idx))
filename = varargin{idx+1};
varargin([idx,idx+1]) = [];
end
h = plot(varargin{:});
varagout{1} = h;
if (~isempty(idx))
save(filename, h);
end
varagout{2} = filename;
This function works as plot except it saves the figure to file in case a filename is specified. In case the developer needs the handle it will be returned and in case the developer wants the save directory it can be returned as well. None of these arguments are necessary though. The developer may want to use this function as a standard plot function and this means that the user may want to call myplot as myplot(x,y);which does not return a value. Further note that even if 'filename' is not specified, the function can still return 2 outputs. The second output may be an empty array of char, but two outputs for the caller will never cause a crash.
Also, note that no further error handling is required. The only unchecked crashes are in plot and save. How this is handled may be different for different users and this means that it only is reasonable to let the user catch the error and handle it (as he would have done if save or plot would have thrown).
Apart from this you may also want to have a check so that the number of output variables are within the correct range (in this case 0,1 or 2 outputs).

Use variable number of output while assigning to varargout

I'm making a generic subsref for my classA, which has an attribute attrA that is a classB instance.
So far, it's working, it lets me do things like
x = objA.attr1.methB(),
which was what I was trying to do to do in the first place.
function this = Class1(varargin)
this.attrA = ClassB()
this = class(this,'ClassA')
function this = ClassB()
this.AttrB1 = 'valueB1'
this.AttrB2 = 'valueB2'
function out = methB
out = this.AttrB2
The problem I stumbled upon is this:
when the call to a method is executed in my subsref, I do it like this (detecting that it's a method etc is done before):
methName = index(1).subs;
args = index(2).subs;
if iscell(args)
varargout = {feval(methName,this,args{:})};
else
varargout = {feval(methName,this,args)};
end %end if iscell
The problem is that when the methName method supports variable number of outputs, this varargout is not equivalent to [x,y,...] (the number of outputs should be assigned in the call to subsref, so methName always returns a single output, which is not always what I want (almost, but not always).
How would I let methName know how many outputs I want? (I don't want to have to pass N as a parameter).
I'm thinking something like creating a string str='[out1,out2,out3...]'
and then doing something like
eval([
str ...
'= {feval(methName,this,args{:})};'...
])
But I keep thinking there must be a more elegant way of doing it.
If the number of outputs you expect is dependent on the output arguments requested from your subsref, you can simply use nargout like this:
[varargout{1:nargout}] = feval(methName,this,args{:});
This solution worked, but I needed to add a little something for single outputs:
if iscell(args)
[argout{:}] = feval(methName,this,args{:});
else
[argout{:}]= {feval(methName,this,args)};
end %end if iscell`
if isSingleCell(argout) && iscell(argout{1})`
v = argout{1};
argout{1}=v{1};
end
I'm not sure, but it may be that the last bit was only necessary to fix something else ( I had to fix a lot of other things to make this work). I'll get back to it when I finish what I was trying to do with this class

How to write a function that does not throw a "wrong number of arguments" error

I am trying to write a minimal function that can be called with a variable number of arguments but that will not throw a wrong number of arguments error if miscalled.
Here is where I start from :
function varargout=fname(varargin)
% FNAME
% Usage: output=fname(input)
% Arguments check
if(nargin~=1 || nargout~=1)
disp('Function fname requires one input argument');
disp('and one output argument');
disp('Try `help fname`');
varargout(1:nargout)={0};
return;
end
input=varargin{1};
output=input;
varargout(1)={output};
end
However this does not work as I would like it to. Is there a way to write a function that :
never throw a "wrong number of arguments" error (so that the rest of the execution can continue)
accepts variable number of input and output arguments and checks them inside the function
(maybe more tricky) if the number of input / output arguments is not correct, does not replace the value of the provided output arguments (so that any misplaced call does not erase the previous value of the output argument)
I am open to any suggestions / other methods.
Thank you for your help.
UPDATE: thanks to #Amro for his answer, I guess what I miss here is either a call by address of reference for Matlab functions or a way to interrupt a function without returning anything and without stopping the rest of the execution.
Here is one way to implement your function:
function varargout = fname(input,varargin)
%# FNAME
%# Usage: output=fname(input)
%%# INPUT
if nargin<1
varargout(1:nargout) = {[]};
warning('Not enough input arguments.'), return
end
if ~isempty(varargin)
warning('Too many input arguments.')
end
%%# YOUR CODE: manipulate input, and compute output
output = input;
%%# OUTPUT
varargout{1} = output;
if nargout>1
warning('Too many output arguments.')
varargout(2:nargout) = {[]};
end
end
Obviously you can customize the warning messages to your liking...
Also, if you want your function to simply print the message instead of issuing warnings, replace all WARNING calls with simple DISP function calls.
Examples of function call:
fname()
fname(1)
fname(1,2)
x = fname()
x = fname(1)
x = fname(1,2)
[x,y] = fname()
[x,y] = fname(1)
[x,y] = fname(1,2)
The above calls execute as expected (showing warning messages when applicable). One caveat though, in the last three calls, if the variable y already existed in the workspace prior to the calls, it would be overwritten by the empty value y=[] in each...
If I understand your question correctly, then the answer is no. If a caller calls a function like this:
[a, b, c] = fname('foo');
then fname is required to return (at least) three outputs. There's no way to tell MATLAB that it should leave b and c alone if fname only returns one output.

MATLAB- passing a function handle parameter into another function as a handle

Working on an assignment involving Genetic Algorithms (loads of headaches, loads of fun). I need to be able to test differing crossover methods and differing mutation methods, to compare their results (part of the paper I have to write for the course). As such, I want to just pass the function names into the Repopulate method, as function handles.
function newpop = Repopulate(population, crossOverMethod, mutationMethod)
...
child = crossOverMethod(parent1, parent2, #mutationMethod);
...
function child = crossOverMethod(parent1, parent2, mutationMethod)
...
if (mutateThisChild == true)
child = mutationMethod(child);
end
...
The key point here is like 3, parameter 3: how do I pass mutationMethod down another level? If I use the # symbol, I get told:
"mutationMethod" was previously used as a variable,
conflicting with its use here as the name of a function or command.
If I don't use the # symbol, then mutationMethod gets called, with no parameters, and is quite unhappy.
While I am aware that yes, I could just rewrite my code to make it work differently, I'm now curious as to how to make it actually work.
Any help is greatly appreciated.
Actually just dont use the # symbol, use it when you call the Repopulate function instead.
Example:
function x = fun1(a,m)
x = fun2(a,m);
end
function y = fun2(b,n)
y = n(b);
end
which we call as:
> fun1([1 2 3], #sum)
6
Refer to the documentation for Passing Function Handle Arguments
Note you can check if the argument is a function handle by: isa(m,'function_handle'). Therefore you can make your function Repopulate more flexible by accepting both a function handle and a function name as a string:
function x = fun(a,m)
if ischar(m)
f = str2func(m);
elseif isa(m,'function_handle')
f = m;
else
error('expecting a function')
end
x = fun2(a,f);
end
which now can be called both ways:
fun1([1 2 3], #sum)
fun1([1 2 3], 'sum')