How do I suppress lines of code inside one function when that function is being called from within another function? - matlab

I have two functions, one is called from inside of another. I want certain parts of the first function to not execute when being called within the second function.
function vvec = vecVelocity(varargin);
%must be preceded with a 'syms var real' declaration where var is
%the parameter of your vector function
if nargin > 1 & nargin < 3
r = [sym(varargin(1:end))];
elseif nargin > 3
disp('too many inputs')
return
else r = [sym(varargin(1))];
end
if length(r) < 3
r = [r,0];
end
dr = diff(r);
uT = vecUnitTan(r);
speed = sqrt(sum(dr.^2));
v = speed*uT;
vvec = matlabFunction(v);
disp(['Simplified Symbolic Form: ' char(simplify(sym(vvec)))]);
I would like to suppress this last line disp(...) from appearing when I call this following second function from the command window
function speed = vecSpeed(r);
%must be preceded with a 'syms var real' declaration where var is
%the parameter of your vector function
v = sym(vecVelocity(r));
sp = sqrt(sum(v.^2));
speed = matlabFunction(sp);
disp(['Simplified Symbolic Form: ' char(simplify(sym(speed)))]);
At the moment, calling the vecSpeed function, causes a bunch of statements to be displayed from other preceding functions that are called from within the vecSpeed function (and some that are called from within the vecVelocity function), but I only want the disp(...) statement from the vecSpeed function to be called, not any of the others.

In the first function, you can put a block of codes in
if numel(dbstack) == 1
% Your code block
end
to prevent them to be executed unless the function is being called directly from Command Window.
Another way is to check for existence of some variables like debug_1, debug_2 etc.. which you can pass from the 2nd function when you call the 1st function.

Related

Function 'subsindex' is not defined for values of class 'struct'

I am using the matlab to solve a simple model in economics. But I came across an error
Function 'subsindex' is not defined for values of class 'struct'
when I run the last line of code.
omega=mkt_share(Par,w,Grid);
It appears wired to me as I call this function repeatedly in the code before reaching the last line, it works fine. Could anyone inform me how to solve the problem? Thanks!
I post the full code of my program as following
clear all
Par.theta = 1.5;
Par.gamma = 6;
Par.beta = 0.1;
Par.zeta = 15;
Par.n = 100;
Grid.q = sort( gprnd(1/Par.zeta,1/Par.zeta,1,Par.n,1));
Grid.q = Grid.q./Grid.q(1);
w0=0.0001;
We0=tot_mkt_share(Par,w0,Grid);
mkt_share=mkt_share(Par,w0,Grid);
w1=0.01;
We1=tot_mkt_share(Par,w1,Grid);
while(We0*We1>0)
if We0<0
w0=w0*0.5;
We0=tot_mkt_share(Par,w0,Grid);
end
if We1>0
w1=w1*1.5;
We1=tot_mkt_share(Par,w1,Grid);
end
end
iconv2=0;
tol2=0.0000001;
maxit2=1000;
it2=1;
while(iconv2==0 && it2<=maxit2)
w=(w0+w1)/2;
We=tot_mkt_share(Par,w,Grid);
if abs(We)<tol2
iconv2=1;
disp('wage has converged in')
it2
else
if We*We1>0
w1=w;
else
w0=w;
end
it2=it2+1;
end
end
if it2>=maxit2
disp('Warning: Zero profit condition not satisfied')
end
omega=mkt_share(Par,w,Grid);
The code for function mkt_share
function omega=mkt_share(Par,w0,Grid)
omega=w0;
for i=2:Par.n
rel_q=Grid.q(i);
fcn=#(omega) (rel_q)^(-Par.gamma)*(omega/w0)^(1-Par.beta*Par.gamma)*((1-
((1-w0)/Par.gamma+w0/Par.theta))/(1-
((1omega)/Par.gamma+omega/Par.theta)))^(Par.gamma-1)-1;
omega_i=fsolve(fcn,w0);
omega=[omega',omega_i]';
end
The code for function tot_mkt_share, which calls function mkt_share
function tot_mkt_share=tot_mkt_share(Par,w0,Grid)
tot_mkt_share=sum(mkt_share(Par,w0,Grid))-1;
When you do:
mkt_share=mkt_share(Par,w0,Grid);
you create a variable with the same name as the function. From this point on, the function is no longer accessible, it is shadowed. The last line attempts to index into this variable, rather than call the function as you intend, because the function is shadowed.

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

Function with different return variables

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

Why are the values passed to a method saved as an object?

I have a class with a scheduler function that is supposed to insert characters into a cell array:
classdef timeline < handle
properties
schedule
i
%other properties
end
methods
%other functions
function t = timeline()
%other initializations
t.schedule = cell(1,738);
t.i = 1;
end
function scheduler(t, g, fT)
if nargin == 2
fT = t.i;
end
if strcmp(g,'science')
'science' % eclipse occurs after
for j = (fT+t.sTime+1) : (fT+t.sTime+1+t.eTime)
t.schedule{j} = 'e';
end
elseif strcmp(g,'pass')
'pass' % science occurs 2 hrs after end
for j = (fT) : (fT+t.pTime)
t.schedule{j} = 'p'
end
for j = (fT+t.pTime+121) : (fT+t.pTime+120+t.sTime)
t.schedule{j} = 's';
end
scheduler(t, 'science', fT+t.pTime+120);
end
end
end
end
In the command window, I define my object t = timeline() and a mode g = 'pass' and then call the scheduler, t.scheduler(t,g).
It doesn't change the schedule property. What's going on inside the if statements to write the schedule isn't the problem I am concerned with. I put outputs in each part of the if statement, and found that strcmp is returning false and skipping over the whole block. So, I added a break point in the scheduler function, and found that for some reason g is passed to the function as another timeline object instead of the string 'pass'. Why is this?
When you call a method for an object you can use dot notation or function notation. Dot notation means you call the method using the dot operator on the object instance. For example,
obj.methodName(args);
In function notation you pass the object instance variable as the first argument to the method. For example,
methodName(obj, args);
Both the above calls are equivalent and call the same method in the object. In both the calls MATLAB passes obj as input to the method. Note the absence of obj as an argument in the dot notation. In dot notation obj, is added as an input argument before your args. In your code you are mixing both of these options. So you got two obj arguments for your method.
Relevant documentation is at http://www.mathworks.com/help/matlab/matlab_oop/method-invocation.html

Passing a variable out of local functions

I'm having some trouble with local functions within my code so I've pasted a simple example below:
function [avg,testvar] = test(x) %Warning
n = length(x);
avg = mymean(x,n);
end
function [a,testvar] = mymean(v,n)
a = sum(v)/n;
testvar=123;
end
One can probably see what I'm attempting; to pass testvar out of the local functions. However Matlab returns the warning:
"The function return value 'testvar' might be unset"
with respect to the line I've commented "%Warning".
What's the best way of getting around this?
You need to specify the value of the second output of test(). Otherwise how can MATLAB know what its value is supposed to be? It doesn't know the second output of mymean() should be routed to the second output of test(). Perhaps this will solve your problem.
function [avg,testvar] = test(x) %Warning
n = length(x);
[avg, testvar] = mymean(x,n);
end
function [a,testvar] = mymean(v,n)
a = sum(v)/n;
testvar=123;
end
The variables between brackets after function are the output variables.
In your first function, you did not assign any value to testvar hence the warning. If you add testvar = 123; in the first function, the warning goes away. Or you can remove testvar from the output variables, leaving:
function avg = test(x)