% Dog.m -------------------------------------------------
classdef Dog
methods
function varargout = subsref(obj, x)
varargout = subsref_overloaded(obj, x);
end
end
end
% subsref_overloaded.m ----------------------------------
function varargout = subsref_overloaded(obj, x)
[varargout{1:nargout}] = builtin('subsref', obj, x);
end
d=Dog(), and d() yields
Maximum recursion limit of 500 reached.
Error in Dog (line 2)
[varargout{1:nargout}] = builtin('subsref', obj, x);
Caused by:
Maximum recursion limit of 500 reached.
Why, and can it be fixed? It's strange since it copies code straight from implementation, and in debugger, builtin('subsref', obj, x) called while in Dog.m works as expected, but not while in subsref_overloaded.m.
Context: I'm overloading subsref like here, but that's verbose to reuse so I want to make something like subsref_overloaded(obj, x, fn) and output fn(x).
builtin cares about where it's called from for some reason - it works properly if called from within the class itself (thanks #CrissLuengo). The following is an imperfect workaround
classdef Dog
methods
function varargout = subsref(obj, x)
[varargout{1:nargout}] = subsref_overloaded(obj, x);
if ~isempty(varargout) && varargout{1} == "special token"
[varargout{1:nargout}] = builtin('subsref', obj, x);
end
end
end
end
function varargout = subsref_overloaded(obj, x)
if % your cond here
% your logic here
else
[varargout{1:nargout}] = "special token";
end
end
Better alternatives / explanations welcome.
Related
I tried to test with my really simple code as below, but the error is "Too many output arguments."
function func1(x,y)
plot(x, y), xlabel('x'), ylabel('Sin(x)'), title('Sin(x) Graph'),
grid on, axis equal
end
function func2(x,y)
plot(x, y), xlabel('x'), ylabel('Cos(x)'), title('Cos(x) Graph'),
grid on, axis equal
end
the main is
x = 0:0.01:10;
y1 = sin(x);
y2 = cos(x);
funcs = {#func1, #func2} ; % let fun1, fun2 be two functions
arguments = {x y1;x y2} ; % write the inputs of each function
solutions = cell(1,2); % initialize the solution
% use of parfor
parfor ii = 1:2
solutions{ii}=funcs{ii}(arguments{ii,:});
end
Please help!!!
The way you call the function
solutions{ii}=funcs{ii}(arguments{ii,:});
Expects an output, which you're assigning to solutions{ii}.
This wouldn't work within a normal loop, or even without a loop, the fact that you're trying to write a parfor is immaterial here...
Your functions are defined as
function func1(x,y)
% ...
function func2(x,y)
% ...
Neither of these have output arguments, so it's unclear what you expect to be assigning to solutions{ii} - this exactly matches the error message you're seeing "too many output arguments".
If you expect an output from your function, then declare one
function z = func1(x,y)
z = x + y;
% other stuff
end
Otherwise, don't request an output within the loop
parfor ii = 1:2
funcs{ii}(arguments{ii,:});
end
I have written the following Matlab function:
function EulerMethod(t_min,t_max,h,f,Y,yzero)
tlist = t_min:h:t_max;
N = (t_max - t_min)/h;
ylist = transpose(zeros(N+1,1));
ylist(1) = yzero;
for i=1:N
term = f(tlist(i),ylist(i))*h;
ylist(i+1) = ylist(i) + term;
end
yrange = Y(tlist);
% modified to generate a new figure window each time.
figure;
plot(tlist,yrange,'red','LineWidth', 2);
hold;
plot(tlist,ylist,'blue','LineWidth', 2);
plot(tlist, abs(yrange - ylist),'magenta','LineWidth', 2)
% modified to wrap the title.
title({'Graphs of the True Solution, Euler Solution,', 'and the Absolute Value of the Global Error (GE)'})
xlabel('t')
ylabel('Y(t)')
legend({'True Solution','Euler Solution', 'Absolute Value of the GE'},'Location','southwest')
end
I now try and call this function in another script. The variables f and Y in the function are symbolic functions; so, in the other file, I first declare these functions before calling this function. Here's the code:
clc
syms f(t,y)
syms Y(t)
f(t,y) = -y + 2.0*cos(t); %This the derivative of the function whose solution we're trying to computed
Y(t) = sin(t) + cos(t); %This is the true solution;
% Calling function
EulerMethod(0.0, 6.0, 0.2, f, Y, 1.0);
I, however, get errors when I run the second script. Can anyone help me figure out what's going wrong? I suspect this may be because of the way I have both input and used the symbolic functions f and Y but I am not sure.
With an anonymous function, you can return any number of outputs. What I need is to be able to use functors (anonymous functions as arguments of other functions), while not knowing how many outputs I will get.
This is to avoid code duplication by injecting functions calls inside a while loop which is reused in many functions.
Example:
function y = foo( x )
y = x;
end
function [y1, y2] = goo( x1, x2 )
y1 = x1;
y2 = x2;
end
function [ varargout ] = yolo( functor, varargin )
varargout = functor(varargin{:});
end
I want to be able to call:
y = yolo(#foo, 2)
[y1, y2] = yolo(#goo, 3, 4);
Is there any way to achieve this ?
Thanks
It is not possible to get the number of outputs of an anonymous function (a function handle to an inline function) because the output is always varargout and therefore nargout is always going to return -1
myfunc = #(x, y) x + y;
nargout(myfunc)
% -1
However, it looks like you don't have anonymous functions, but rather just function handles to normal functions that are defined in an .m file and have an explicit number of output arguments. In this case, you can combine nargout with {:} indexing to fill varargout with all of the output arguments.
function y = foo(x)
y = x;
end
function [y1, y2] = goo(x1, x2)
y1 = x1;
y2 = x2;
end
function varargout = yolo(functor, varargin)
[varargout{1:nargout(functor)}] = functor(varargin{:});
end
y = yolo(#foo, 2)
[y1, y2] = yolo(#goo, 3, 4)
I have a class function that uses ODE45 to solve some equations. I have another, private class function that represents the odefunction that ODE45 needs to solve. However, I can't figure out how to pass a handle of the class's ode function to ODE45. Here is the sample code:
class ODESolver < handle
methods (Access = public)
function obj = RunODE(obj, t, y0)
[~, Z] = ode45(#ODEFunction, t, y0);
end
end
methods (Access = private)
function dy = ODEFunction(t,y)
% Calculate dy here.
end
end
end
When I run this, i get an error saying:
Undefined function 'ODEFunction' for input arguments of type 'double'.
If I move ODEFunction outside of the class and put it in its own *.m file, the code runs fine. I've also tried using "#obj.ODEFunction" in the ode45 call, but then it says:
Too many input arguments.
What's the best way to keep ODEFunction inside of my class and still be able to pass it's handle to ode45?
Your private ODEFunction is not a static method, so you should write:
classdef ODESolver < handle
methods (Access = public)
function obj = RunODE(obj, t, y0)
[~, Z] = ode45(#(tt, yy)obj.ODEFunction(tt, yy), t, y0);
end
end
methods (Access = private)
function dy = ODEFunction(obj, t,y)
dy = 0.1; % Calculate dy here.
end
end
end
NB: You also forgot to pass obj as first argument of private ODEFunction ... I'm writing example with static method and will paste it here once tested.
Edit
Here is how you should write things if you intented to have private static ODEFunction in your class:
classdef ODESolver < handle
methods (Access = public)
function obj = RunODE(obj, t, y0)
[~, Z] = ode45(#(tt, yy)ODESolver.ODEFunction(tt, yy), t, y0);
end
end
methods (Static, Access = private)
function dy = ODEFunction(t,y)
dy = 0.1; % Calculate dy here.
end
end
end
I have two Matlab functions f=fun1(x) and f=fun2(x,y) which are very alike and I would like to integrate them into a single function f=fun(x,y).
For the first function I have
function f=fun1(x)
N=1000; % Some large number.
for j=1:N
f=x^2;
end
and for the second function
function f=fun2(x,y)
N=1000; % Some large number.
for j=1:N
f=x^2;
f=f+y;
end
. So actually fun1 is sort of a subfunction of fun2. I would like to construct a function f=fun(x,y,method_number) like
function f=fun(x,y,method_number)
N=1000; % Some large number.
for j=1:N
f=x^2; % If method_number==1 run only this command....
f=f+y; % If method_number==2 run also this command.
end
This is just a short simplified example of the problem I want to solve. My real problem is that I have three long functions f=fun1(x,y,z), f=fun2(x,y) and f=fun3(x) with several resemblances and of which fun3 is a subfunction of fun2 and fun2 is a subfunction of fun1 in the same meaning as here above. I do not believe using switch-case or if-else everywhere is an option since N can be very large, which would be inefficient. Furthermore, it would completely destroy the layout of the code.
In your case it seem each of your function have a different number of input argument. If it is the case, the matlab function nargin can detect that and you do not have to specify an additional method parameter.
For example:
function f = fun(x,y,z)
switch nargin
case 1
f = x.^2; %// run only if ONE argument was specified
case 2
f = fun(x) + y; %// run only if TWO arguments were specified
case 3
f = fun(x,y) ./ z ; %// run only if THREE arguments were specified
otherwise
disp('Houston, we have a problem !!') ; %// run if NO or more than 3 arguments were specified
end
You can call f with one argument, two or three without trouble, Matlab will only execute the function corresponding to the proper number of argument.
The function, when passed with 3 arguments, can call on itself to calculate the part with 2 argument (which can call on itself to calculate the part from the first argument).
Case two: If the recursion really cannot be taken out of the loop, the classic if ... then will work:
function f = fun(x,y,z)
if nargin == 3
threeArgs = true ;
twoArgs = true ;
elseif nargin == 2
threeArgs = false ;
twoArgs = true ;
elseif nargin == 1
threeArgs = false ;
twoArgs = false ;
end
for it=1:1e6
f = x.^2; %// If method_number==1 run only this command....
%// ... other computations
if twoArgs
f = f + y ; %// If method_number==2 run also this command.
%// ... other computations
if threeArgs
f = f ./z ; %// If method_number==3 run also this command.
%// ... other computations
end
%// ... other computations only relevant to f(x,y)
end
%// ... other computations only relevant to f(x)
end
This would totally exclude recursion and would insure the minimum number of computation.
Now I realise this looks a bit clumsy code and you asked for a solution without if ... then and switch. Depending on your calculation, there is a method which can avoid any if or switch but may not be practical for all cases.
The idea is to assign an invariant operator to y or z in case they are not called.
Example:
function f = fun(x,y,z)
if nargin < 3 ; z = 1 ; end
if nargin < 2 ; y = 0 ; end
for it=1:1e6
f = x.^2;
%// ... other computations just based on X
f = f + y ; %// This always run, but if "y" wasn't specified, it does not modify the result (f+0=f)
%// ... other computations
f = f ./z ; %// This always run, but if "z" wasn't specified, it does not modify the result (f./1=f)
%// ... other computations
end
This avoid any flow branch in the code but i would only keep this method for simple cases, because the computations are always done regardless of the case (although may be some JIT compiler are smart enough to not bother doing 'no effect' operations).
You can avoid checking for the number of input arguments nargin N-times by duplicating code. You will check once, which computation should be done and repeat it N times. In this example, the for-loop is the duplicated code. To some extent, this might be okay.
function f = fun(x, y, z)
N = 1000;
switch nargin
%// Do something if only x is given
case 1
for j = 1:N
f = x.^2;
end
%// Do something else if only x and y are given
case 2
for j = 1:N
f = x.^2 + y;
end
%// Do something else if x, y and z are given
case 3
for j = 1:N
f = x.^2 + y - z;
end
otherwise
error('Use fun.m with 1, 2 or 3 arguments only!');
end
end
This is a variation of Hoki`s answer. In fact, I started from it adding the for-loop and removing the recursive function calls by adding duplicated code.