classdef Dog
methods
function out = bark(obj, text)
% disp(text)
out = 1;
end
function ind = end(~, ~, ~)
error("`end` forbidden")
end
end
end
d=Dog(), d(end) will error but d.bark(end) won't.
Uncommenting disp(text) instead errors as Not enough input arguments, but that's not same as forbidding end as input to bark.
d.bark(end, end) errors as Too many input arguments.
Can end be forbidden (or detected) as input to any method of d?
It looks like d.bark(end) calls d.bark first, obtaining the output array out, then calls end(out,1,1). This end is not your overloaded function, it is the version for whatever type out is, which in your case is double. So this is the built-in out. This end returns 1. Finally, it calls d.bark(1).
I think this is a strange behavior. MATLAB only does this for class methods, not for free functions. For example sqrt(end) or eps(end) give the error "The end operator must be used within an array index expression.".
I don't think there is a way around this, it is built-in MATLAB behavior, it would require changing the interpreter to override the behavior.
Related
I was having a doubt today :).
For
A=1;
is there any function f that does the same? like following
f(A,1);
It could help me in some cases like in cellfun or something like that.
You can do this easily if your variable A is a handle class object, thus giving it reference behavior. You could then create a method f for the class that accepts a class object A and a new value for it to store. See Object-Oriented Programming for more information.
For data types like double or cell there are no built-in functions that work this way. You could make your own function using assignin and inputname like so:
function f(var, value)
assignin('caller', inputname(1), value);
end
And call it as follows, with A already defined:
A = 0;
f(A, 1); % Changes the value of A to 1
However, this would generally be considered bad practice as it makes the code harder to follow, as call-by-value behavior is the expected norm.
In general no, MATLAB functions cannot change their input.
But, if you are brave, you can create a MEX-file that breaks that promise and does change the input. In a MEX-file you can write to the input array, but doing so carelessly causes havoc. For example,
B = A;
f(A,1); % <- modifies A
would cause B to also be modified, because MATLAB delays copying the data when you do B = A. That is, the two variables point to the same data until you modify one, at which point the data is copied. But in a MEX-file you can write to a matrix without doing this check, thereby modifying B also. The link I provided shows how to modify A carefully.
You can call methods of an object using function handles. Example:
classdef foo
methods
function value=foofun(this)
value=1;
end
end
end
and then
fun=#foofun;
fun(foo);
The handle is just a string I guess, and it doesn't bother Matlab that it can't tell which function is intended before the handle is used. The same handle could even be used to call different methods if different type objects are used as the first parameter.
To capture the outputs of the function you can do this:
outputs=cell(numberOfOutputs,1);
[outputs{:}]=fun(foo);
However, if the function handle was a parameter in the code, then the number of outputs is a problem. For handles to normal functions nargout would solve that, but now nargout can't help because the handle doesn't determine on it's own which function will be called. nargout would need a second input, the type of the object that is going to be used.
It's a bit inelegant to need both the handle and the number of outputs as parameters. Is there another way to call methods indirectly and still capture all the outputs?
Use-case
Imagine a graph with nodes and edges between nodes. Each edge has a few data objects associated with that particular edge. I'm interested in doing various calculations on those data objects.
Examples
Take all the data objects associated with a specific edge and calculate spectra of those objects.
Use the prettiest data object from each edge and get the spectra from those objects.
Choose ten edges randomly, choose randomly one data object from each of those and then compare the objects with a specific, separate, object.
Design
The idea is to separate the selection of the objects and the calculations into different functions. This way the user can combine any calculation with any selection method. Each time a new method is added to the data objects, it can already be called with the existing object selection methods and each time a new selection method is added, it can be used with all the available calculation methods.
A simplified version of a function I'm currently using looks like this
function [ outs ] = callForEach(objects, fun, numberOfOutputs, extraArguments)
for ii=1:length(objects)
out=cell(1,numberOfOutputs);
[out{:}]=fun(objects{ii},extraArguments{ii,:});
outs(ii,:)=out;
end
end
I'd like to be able avoid the parameter numberOfOutputs. It's an inconvenience for the user and it's more error prone to do it like this.
I guess I could just force a same interface for every method: everybody returns a cell array if they need several outputs. I can then assign that cell array, or whatever it is that is returned, into a single cell. However all the built-in functions seem to prefer to use multiple outputs instead, so there's at least a stylistic difference. If I ever wanted to use one of the built-ins as the handle, I'd need to write a wrapper to make the built-in conform to the interface.
Check this class as foo.m. By running foo.main() you recover most of the addressed questions.
This is not the maximum elegance in OOP, but you have Matlab as is.
Remember the obj variable is MANDATORY, in and out. No obj, no dot fanciness.
The final calls, HAVE to include the f1. Putting a ~ lost not only the fanciness, but the object and its data.
Besides the obj treatment, nargin|nargout|varargin|varargout are valid inside a function body only, and is runtime dependent, as usually. One cannot in general know how much parameters you will throw, because is equivalent to the length of the varargout cell.
classdef foo
properties
value;
end
methods
function [obj,flag]=fun1(obj,this)
obj.value=this+1;
flag=1;
end
function [obj,flag]=fun2(obj,this)
obj.value=2*this;
flag=2;
end
function [obj,varargout]=fun3(obj,varargin)
for i=1:nargin-1
varargout{i}=varargin{i};
end
obj.value=0;
end
end
methods (Static)
function main()
if 0
%% Run this line
foo.main()
end
f1=foo();
[f1,flag]=f1.fun1(10);
flag
f1.value
f=#fun2;
%[f1,flag]=f1.f(10); % fails
flag
f1.value
[f1,flag]=f1.('fun2')(10);
flag
f1.value
[~,flag]=f1.fun2(10); % fails
flag
f1.value
[f1,a1,a2,a3,a4]=f1.fun3('x1',2,[],#(x)(x>1))
end
end
end
I defined the following class
classdef TimerManager < handle
methods (Access = private)
function obj = TimerManager()
end
end
methods (Static)
function singleObj = getInstance(varargin)
varargin{1}
singleObj = TimerManager();
end
end
methods
function foo(obj)
end
end
end
I found the following code works differently w/ or w/o ;
Is this expected? or if I missed anything?
>> TimerManager.getInstance(0).foo()
ans =
0
>> TimerManager.getInstance(0).foo();
Index exceeds matrix dimensions.
Error in TimerManager.getInstance (line 13)
varargin{1}
If I use nargin in side getInstance, it is 0 if I put ; at the end.
Your error has nothing to do with the semi-colon. This has to do with the way that MATLAB handles subscripted referencing of objects (subsref).
The (Detailed) Issue
In MATLAB, you cannot "chain" subscripted referencing. For example if we create a cell array, we can't immediately index into this cell array without first assigning it to a temporary variable:
X1 = {'X1', 'X2', 'X3'}{1}
Error: Unbalanced or unexpected parenthesis or bracket.
The same applies for accessing the property or method of an object which is returned by a function. In your case, TimerManager.getInstance returns an instance which you must first assign to a temporary variable before being able to access it's foo method.
instance = TimerManager.getInstance(0);
fooResult = instance.foo();
MATLAB makes an attempt to throw an error or warning when it thinks that you're trying to "chain" these subscript references together, but if there is a scenario where an order of subscript operations is valid, then it is unable to throw the appropriate error. You are experiencing one of those cases.
The syntax that you are using is something like the following:
a.b(c).d()
This is valid if a.b is an array of structs with a field of d which is a function handle. In this case, c is an index.
When MATLAB parses this, it's going to retrieve the value of a.b, then ensure that c is a positive integer (a valid index) and is within the bounds of the array a.b. Then once that's been confirmed, MATLAB will access the d field and invoke it.
If we go back to your code for a second, we can comment out the varargin{1} line and get a more useful error message.
TimerManager.getInstance(0).foo();
Subscript indices must either be real positive integers or logicals.
Ok so that kind of makes sense, MATLAB is treating TimerManager.getInstance as a struct array and trying to index into it with the 0 which is obviously invalid and results in the error.
With respect to the actual error that you reported, note above that I said that before applying subscript referencing on the supposed struct array, MATLAB needs to first get the current value of TimerManager.getInstance. Because MATLAB thinks that this is just a struct array it's not going to pass any input arguments to it and this is resulting in varargin being empty and the error that you're seeing.
So your statement is functionally the same as:
instance = TimerManager.getInstance; % No input arguments
instance(0).foo() % Indexing error
Note that this does work if the "input" to getInstance is 1 since this is a valid index into the 1 x 1 array of TimerManager instances returned when you call Timermanager.getInstance with no inputs.
TimerManager.getInstance(1).foo();
Potential Solutions
Use a temporary variable
instance = TimerManager.getInstance(0);
fooResult = instance.foo();
Or use the method(obj) notation for invoking the method rather than the obj.method() notation.
foo(TimerManager.getInstance(0))
A Note on Octave
None of this is going to be an issue in Octave since it allows "chaining" these subscript references together without the need for a temporary variable.
I'm teaching myself the basics of MATLAB, and I'm stuck on how to create errors for functions.
Here is my attempt:
function kinetic = KE(m,v)
KE = 0.5*m*v*v
%error messages
if (isempty(m))
% mass is empty
error('No mass given (argument 1)');
elseif (isempty(v))
% velocity is empty
error('No velocity given (argument 2)');
end
fprintf('The kinetic energy is %d joules\n', KE);
So if the user doesn't specify 2 variables, the function gives an error telling the user which variable they didn't specify. When I try to get this error message, MATLAB returns a generic error message:
kinetic(,3)
kinetic(,3)
|
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.
I don't know how to fix this. I've tried replacing the arguments of the isempty with arg1 or arg2, but it made no difference. Then I tried copying the example code at http://www.mathworks.co.uk/help/matlab/ref/error.html but it still didn't help.
How do you generate specific errors for functions of several variables?
I know this is quite a basic question, any help will be appreciated.
There are a few problems with your code:
The syntax of a function signature is
(Square brackets are optional if the function only has one output.) Here, kinetic is the output of your function, whereas KE is the name of the function; therefore, a call to your function has the form
KE(m,v)
not
kinetic(m,v)
The isempty function is only meant to detect whether an array (and in MATLAB, everything is a 2D array, by default) is empty or not. You can't use it to detect whether a function call is missing arguments.
As pointed out by Oliver, KE(,v) is not correct MATLAB syntax, and MATLAB will stop in its tracks and let the user know of her blunder before it attempts to process the function call.
What you probably want to do, here, is to define a variadic function, i.e. a function that can accept a varying number of arguments. Use varargin and nargin for that; for more details, look those up in the MATLAB help.
Finally, you probably want to
vectorize your function, i.e. make it compatible with vector inputs, by using entrywise operators (.* and .^),
prevent results from being printed in the Command Window, by terminating all assignment statements with a semicolon.
function kinetic = KE(varargin)
if nargin == 0
error('No mass or velocity given')
elseif nargin == 1
error('No velocity given (argument 2)')
elseif nargin == 2
m=varargin{1};
v=varargin{2};
else
error('Too many inputs')
end
KE = 0.5*m.*v.^2;
fprintf('The kinetic energy is %d joules\n', KE)
I want to overload the indexing via () and {} for one of my MATLAB classes. This is possible by implementing subsref for that class, and it works fine.
However, I also want to keep the default behaviour of indexing via . (i.e. access to methods and properties) for this class. I tried using the following code:
function x = subsref(this, S)
if strcmp(S(1).type, '{}')
% My own implementation here
elseif strcmp(S(1).type, '()')
% My own implementation here
elseif strcmp(S(1).type, '.')
x = builtin('subsref', this, S);
else
error('Unknown index variant.');
end
However, this does not work because I do not know a priori how many output arguments the call to builtin('subsref', this, S) will return. In particular, a method of my class might return a variable number of arguments, with the number of output arguments depending on the number and values of its input arguments. A MATLAB example for subsref (broken link) notes:
When you implement a subsref method for a class, you must implement all subscripted reference explicitly [...]
Is this really the only possible solution? For complex methods this basically means duplicating a lot of the logic. This is definitely not maintainable in my case (large classes with a lot of methods and properties).
Note: I know that this is all about syntactic sugar and that I can always use standard method calls instead of overloading () and {}.
For a partial fix, I think you can use nargout to defer to the caller, which will usually be in a position to know. Any function that's capturing multiple outputs must know at the time of the call how many it's capturing.
This won't let you display multiple argouts at the command line, but should work as long as you're as you're capturing the returned values, as in most code.
function varargout = subsref(this, S)
switch S(1).type
...
case '.'
varargout = cell(1, nargout);
if nargout == 0
builtin('subsref', this, S);
else
[varargout{:}] = builtin('subsref', this, S);
end
end
end
Caveat emptor: this code is not tested, and there's a bunch of finicky edge cases inside the subsref/subsasgn stuff.