I have a C++ file that has some functions in single .cpp file such as
int func1(x)
{
return 1;
}
void func2(x)
{
return 1;
}
int func3(x)
{
return 1;
}
Now, I want to write all above functions in a single matlab file. (If I added an own matlab file for each function, my folder would grow very huge.) Could you suggest to me an easy as well as very clear way to do this in MATLAB?
Currently, I am doing it this way:
function f = perform(func, x);
switch(func)
case 'f1'
f = func1(x);
case 'f2'
f = func2(x);
case 'f3'
f = func3(x);
otherwise
error(['Unknown function ', func]);
end
See local or nested functions. Local functions are most analagous to other programming language syntax.
Local functions, for example:
function f = perform(func, x);
switch(func)
case 'f1'
f = func1(x);
case 'f2'
f = func2(x);
case 'f3'
f = func3(x);
otherwise
error(['Unknown function ', func]);
end
end
function func1(x)
disp(sprintf('func1: %u\n', x))
end
function func2(x)
disp(sprintf('func2: %u\n', x))
end
function func3(x)
disp(sprintf('func3: %u\n', x))
end
Note that neither local nor nested functions are externally callable.
You could organize the functions in package, see Packages Create Namespaces, one for each cpp file as
+module1
func1.m
func2.m
+module2
func1.m
You can then call the functions as
module1.func1(x)
module2.func1(x)
You can, call local functions externally if you set up a bunch of function handles. Not that I recommend this, but I got this setup from a colleague. This code is not robust -- there are almost certainly cases where it'll fail or do bad things.
% code to create callable handles for all subfuncs in some file
%
% first, in the file containing subfuncs:
% this is the "setup" main func
function [p]=To_Call_Subfuncs()
[p,n]=update_function_list();
end
% this creates all the handles by pseudogrepping the subfunction names
function [p,function_names]=update_function_list()
function_names={};
% making p empty allows one to call, e.g. funclist.firstfunc()
p=[];
f=fopen([mfilename() '.m'],'r');
while ~feof(f),
line=fgetl(f);
s= strfind( strtrim(line),'function ') ;
if length(s) && s(1)==1,
s0=find(line=='=');
s1=find(line=='(');
if length(s0)==0,s0=9;end;
if(length(s1)==0), s1 = numel(line)+1;end; %to handle the -1 later on
function_name= strtrim( [line(s0(1)+1:s1(1)-1)] );
if length(function_name),
function_names{end+1}=function_name;
eval( sprintf('p.%s=#%s;', function_name, function_name) );
end;
end;
end;
end
%
%follow this with the functions we actually want to call
function a = firstfunc(x)
a=x;
end
function b = secondfunc(x)
b = x^2;
end
function cnot = thirdfunc
cnot= 17;
end
%
%
% next, in the m-file where some function is calling these subfuncs,
% set up the handles with:
% run(fullfile(dirpath,'the_mfile.m'))
% the_mfile=ans;
% because I don't think run() returns a value --
%% only the called mfile does.
% now you can call the_mfile.firstfunc() and so on.
Related
I have created some MATLAB classes to do some error-checking when I use certain types of structures. This improve development time by preventing errors in the code, but significantly slow down execution time.
One way to get around this is to comment out the set methods inside the class. Is it possible to do this programmatically? For example, only define these methods if a parameter in the constructor is true.
classdef MWE
%MWE Minimum working example
properties
A
B
C
end
methods
function obj = MWE(A, B, C)
if nargin ~= 3
error('A, B and C must all be provided.');
end
obj.A = A;
obj.B = B;
obj.C = C;
end
% function obj = set.A(obj, value)
% validate(obj, value, 'A');
% obj.A = value;
% end
%
% function obj = set.B(obj, value)
% validate(obj, value, 'B');
% obj.B = value;
% end
%
% function obj = set.C(obj, value)
% validate(obj, value, 'C');
% obj.C = value;
% end
end
methods (Access = private)
function validate(obj, value, name)
% Code here
end
end
end
Is it possible to do this programmatically? For example, only define these methods if a parameter in the constructor is true.
After some discussion, I see there are different ways of looking at your question. And, indeed, it may be that you cannot do what you are asking as interpreted by some. Here are two cases, however, that may suffice.
Case 1
You have computationally intensive or otherwise time consuming methods, that you use to "do some error-checking", in a development setting, but want to turn off in a production environment. And, these checks occur when the class is instantiated.
Place these methods in a wrapper function that is called from the constructor.
Here's an example
classdef classFoo
properties(Access=private)
fbar;
end
methods
function this = classFoo(arg1, argN, debugMode)
if(nargin>2 && debugMode)
if(~this.verifyStuff(arg1, argN))
throw(MException('classFoo:ConstructFailure','Could not verify'));
else
this.fbar = timeConsumingFunction();
end
else
this.fbar = 42; % defaultValue;
end
% continue construction
end
function didVerify = verifyStuff(this, varargin)
% complex code
didVerify = randi(2)-1; % 50/50
end
end
end
Then when creating objects you can choose to pass the debug mode flag as true like this:
a=classFoo(1,2,true)
or as false, like this:
a=classFoo(1,2,false)
or not at all, which is the same as the false case, like this:
a=classFoo(1,2)
Case 2
You have two different versions of a get/set method that you are commenting out depending on your development environment.
Add a private member parameter (e.g. isDebugging) and set it at time of construction. Now, instead of commenting out code in your get and set methods, you can handle the different cases with a simple if/else, predicated on your debug state like this:
classdef classFoo
properties(Access=private)
fbar;
isDebugging;
end
methods
function this = classFoo(debugMode)
if(nargin<1 || ~islogical(debugMode))
debugMode = false;
end
this.isDebugging = debugMode;
end
function setfbar(this, fIn)
if(this.isDebugging)
this.fbar = timeConsumingFunction(fIn);
else
this.fbar = fIn; % defaultValue;
end
end
end
end
What I would like to be able to do is programmatically change an anonymous function for example by changing all the plus signs to multiplication signs in the function. This example can in many cases this can be done as follows:
function f2 = changefunction(f1)
fs = func2str(f1);
fs(fs=='+') = '*';
f2 = str2func(fs);
end
But consider the example
f = #(x) x+5;
a = 5;
g = #(x) x+a;
Both f and g will be anonymous functions that adds 5 to whatever you plug into it; however only f will be changed correctly by the changefunction function, whereas g will be changed into a function that will err on any input.
So my question is is it possible to extract the workspace from the function handle and retain it in the new function handle created? I need to do it programmatically and preferably without using the built-in function functions!
One naive implementation is to replace str2func with eval so you are not running into str2func's roadblock of not allowing access to local variables. We can use functions to obtain the workspace information for the input function handle.
For example:
a = 5;
f = #(x) x+a;
finfo = functions(f)
Yields:
finfo =
struct with fields:
function: '#(x)x+a'
type: 'anonymous'
file: 'X:\testcode-matlab\testcode.m'
workspace: {[1×1 struct]}
within_file_path: 'testcode'
Where workspace is a cell array containing a structure (come on MathWorks...) containing all of the variables in your function handle's namespace:
>> wspace = finfo.workspace{1}
wspace =
struct with fields:
a: 5
Using this functionality, the naive solution is to loop through the variables in this workspace, assign them in the namespace of changefunction, then use eval to generate the new function handle.
For example:
function f2 = changefunction_new(f1)
tmp = functions(f1);
workspacevars = tmp.workspace{1};
varnames = fieldnames(workspacevars);
for ii = 1:length(varnames)
evalstr = sprintf('%s = %d;', varnames{ii}, workspacevars.(varnames{ii}));
eval(evalstr);
end
fs = func2str(f1);
fs(fs=='+') = '*';
f2 = eval(fs);
end
Here I'm assuming that the variables are going to be strictly numeric. You can add logic to check the class of the data to be generated if this is not always the case.
With this we have:
a = 5;
g = #(x) x+a;
test1 = changefunction(g);
test2 = changefunction_new(g);
>> g(1)
ans =
6
>> test1(1)
Undefined function or variable 'a'.
Error in testcode>#(x)x*a
>> test2(1)
ans =
5
All that being said, the best solution really is to just explicitly define your function handles. It may be a pain but it's much easier to understand and debug.
A few caveats:
Because eval arbitrarily executes all code passed to it, it can be a very dangerous function that must be used with care.
The documentation for functions warns against using it programmatically, so take care to check behavior as MATLAB versions change:
Use the functions function for querying and debugging purposes only.
Note: Do not use functions programmatically because its behavior could change in subsequent MATLAB® releases.
One possible way to do this is to save the function handle to a .mat file (using the -v7.3 flag so that it creates an easily-modifiable HDF5 file), modify the struct within the file that contains the workspace data for the anonymous function (using the HDF5 tools built into MATLAB), and then load the anonymous function again from the file.
Here is a little function which does exactly that (and it works for relatively simple variable types)
function result = modifyfunc(f, varname, value)
% modifyfunc - Modify the workspace of an anonymous function
%
% INPUTS:
% f: Function Handle, Anonymous function to modify
% varname: String, Name of the variable to modify
% value: Data to replace the specified variable
% If the value is a struct, recursively modify the function handle
if isstruct(value)
fields = fieldnames(value);
result = f;
% Modify each field separately
for k = 1:numel(fields)
% Append the fieldname to the variable name and modify
name = [varname, '.', fields{k}];
result = modifyfunc(result, name, value.(fields{k}));
end
return;
end
% Write the anonymous function to an HDF5 file
fname = tempname;
save(fname, 'f', '-mat', '-v7.3');
% Replace any "." in the variable name with "/" to construct the HDF5 path
varname = strrep(varname, '.' , '/');
% Now modify the data in the file
h5write(fname, ['/#refs#/e/' varname], value);
% Load the modified function handle from the file
result = load(fname, '-mat');
result = result.f;
% Remove the temporary file
delete(fname);
end
And you can use it like:
a = 1;
b = struct('field', 2);
f = #(x)disp(a + b.field + x);
f(10)
% 13
f2 = modifyfunc(f, 'a', 2);
f2(10)
% 14
f3 = modifyfunc(f2, 'b.field', 3);
f3(10)
% 15
b.field = 4;
f4 = modifyfunc(f3, 'b', b);
f4(10)
% 16
Some caveats include:
The replacement data must be the same size as the original data
This relies upon the format of the .mat file which for anonymous functions is completely undocumented so it could fail in future releases.
This currently doesn't work for variables in the function workspace that are cell arrays.
Minimalistic Example:
classdef MyClass
properties
arr
handArr
end
properties(Dependent)
rowAcc
colAcc
end
methods
function obj = MyClass(arr, handRow, handCol)
obj.arr = arr;
obj.handArr{1} = handRow;
if ~isequal(handRow, handCol)
obj.handArr{2} = handCol;
end
end
function r = get.rowAcc(obj)
r = obj.handArr{1}(obj.arr);
end
function c = get.colAcc(obj)
c = obj.handArr{end}(obj.arr);
end
end
end
Now assume I pass equal functions to the constructor, I want the row and col access would also be the same:
f=#(x)#(y) y;
x=MyClass(1, f, f);
isequal(x.rowAcc, x.colAcc) //should be 1
Is this possible?
I have a good reason for this 'insane' requirement:
I have several algorithms which run with 100+ MBs of input and takes those two functions as input, and when they are equal they can be optimized very efficiently; to call the algorithms I need to make transformations to the input functions which are encapsulated inside this class. I can't change the algorithms (not my code) and they use isequal on they're own functions to dispatch.
Two variables pointing to the same anonymous function are considered to be equal
f = #(x)x;
g = f;
isequal(f, g)
% 1
However, if you define the anonymous functions at different times, then they are not considered to be equal because the internal workspaces of the two functions could differ.
f = #(x)x;
g = #(x)x;
isequal(f, g)
% 0
In order to have your property return equal handles, you could have some "shadow" property (accessors_) which caches the accessors and you update these cached values whenever the arr property is changed.
classdef MyClass
properties
arr
handArr
end
properties (Access = 'protected')
accessors_ % An array of accessor functions for rows & columns
end
properties (Dependent)
rowAcc
colAcc
end
methods
function set.arr(obj, value)
% Set the value
obj.arr = value;
% Update the accessors_
self.accessors_ = obj.handArr{1}(obj.arr);
% Only assign another accessor if we have a second one
if numel(obj.handArr) > 1
self.accessors_(2) = obj.handArr{2}(obj.arr);
end
end
function res = get.rowAcc(obj)
res = obj.accessors_(1);
end
function res = get.colAcc(obj)
% If only one was stored, this will return a duplicate of it
res = obj.accessors_(end);
end
end
end
This also has the added benefit that you aren't creating function handles every time that colAcc and rowAcc are retrieved.
I would like to have a class which wraps up a containers.Map. In addition, I want to be able use () indexing to access the sub-map from the parent class, for example:
>> map = containers.Map('Foo', 'Bar');
>> ex = Example(map);
>> ex('Foo')
ans =
Bar
The code for this is below, and it works well. The only problem I am having is with other methods defined on the class. According to the docs, I understand I need to override numArgumentsFromSubscript (somehow?) to help nargout. My crude attempt at simply using numel(obj) as I've seen mentioned online works in most cases, but not when the function you are calling has no output arguments (in which case numel(obj) == 1 ~= 0).
Using the example code below,
>> ex.outGoodbye
ans =
Goodbye
Great! However,
>> ex.sayHello
Error using Example/sayHello
Too many output arguments.
Error in Example/subsref (line 17)
[varargout{1:nargout}] = builtin('subsref', obj, struct);
How can you fix this?
classdef Example
% =====================================================================
properties
map
end
% =====================================================================
methods
% -----------------------------------------------------------------
function obj = Example(map)
obj.map = map;
end
% -----------------------------------------------------------------
function varargout = subsref(obj, struct)
if strcmp(struct(1).type, '()')
[varargout{1:nargout}] = builtin('subsref', obj.map, struct);
else
[varargout{1:nargout}] = builtin('subsref', obj, struct);
end
end
% -----------------------------------------------------------------
function n = numArgumentsFromSubscript(obj, struct, indexingContext)
n = numel(obj); % Necessary to overload subsref - for some reason
end
% -----------------------------------------------------------------
function obj = subsasgn(obj, struct, varargin)
if strcmp(struct(1).type, '()')
obj = builtin('subsasgn', obj.map, struct, varargin{:});
obj = Example(obj);
else
obj = builtin('subsasgn', obj, struct, varargin{:});
end
end
% -----------------------------------------------------------------
function sayHello(obj)
disp('Hello'); % nargout == 0. Does NOT work
end
% -----------------------------------------------------------------
function out = outGoodbye(obj)
out = 'Goodbye'; % nargout > 0. Works
end
% -----------------------------------------------------------------
end
% =====================================================================
end
So digging into this a little further, you have a few options for how to get around this behavior.
method(obj) Calling Convention
You could simply change the way that you're calling the class method. Instead of using the dot notation, you could simply use the standard function notation.
sayHello(ex)
%// vs.
ex.sayHello()
This will avoid calling subsref when calling a method. Also, this is actually the fastest way to call a method of a class in the current iteration of MATLAB's OOP. Additionally, this would require no changes to your current code.
Use nargout to determine number of method outputs
Another option is to add a special case in subsref or numArgumentsFromSubscript that looks for methods called using the dot notation. Then you can explicitly determine the number of output arguments of the method using the following call to nargout.
nArgs = nargout('classname>classname.methodname');
Then you would use that rather than numel(obj). This could be implemented in either numArgumentsFromSubscript or subsref.
numArgumentsFromSubscript
function n = numArgumentsFromSubscript(obj, struct, indexingContext)
%// Check if we are calling obj.method
if strcmp(struct(1).type, '.') && ...
ischar(struct(1).subs) && ismember(struct(1).subs, methods(obj))
%// Determine the package (if any)
cls = class(obj);
parts = regexp(cls, '\.', 'split');
%// Import the package (if any) just into the namespace of this method
if numel(parts) > 1
import(cls);
end
%// Determine number of outputs for this method
n = nargout(sprintf('%s>%s.%s', parts{[end end]}, struct(1).subs));
else
%// Default to numel(obj)
n = numel(obj);
end
end
subsref
function varargout = subsref(obj, struct)
if strcmp(struct(1).type, '()')
[varargout{1:nargout}] = builtin('subsref', obj.map, struct);
%// Check if we are calling obj.method
elseif strcmp(struct(1).type, '.') && ...
ischar(struct(1).subs) && ismember(struct(1).subs, methods(obj))
%// Determine the package (if any)
cls = class(obj);
parts = regexp(cls, '\.', 'split');
%// Import the package (if any) just into the namespace of this method
if numel(parts) > 1
import(cls);
end
%// Determine number of outputs for this method
nout = nargout(sprintf('%s>%s.%s', parts{[end end]}, struct(1).subs));
%// Call builtin subsref with this number of outputs
[varargout{1:nout}] = builtin('subsref', obj, struct);
else
[varargout{1:nargout}] = builtin('subsref', obj, struct);
end
end
Summary
subsref is a pain and a lot of times you end up with a lot of logic to determine what is being called and you'll be right only about 80% of the time. I think that the first approach is the most straightforward, would likely be the most performant (you skip all of the checks in subsref) and deals better with arrays of objects.
If you really wanted to keep the obj.method notation, I would probably recommend changing numArgumentsFromSubscript (rather than subsref) to keep the number of output argument stuff in one place.
Update
Based upon your feedback that the nargout trick doesn't work in cases where the class is contained within a package (foo.bar.Example). I have added a workaround to the above examples. The trick is to call import('foo.bar.Example') prior to calling nargout('Example>Example.sayHello').
Given a file name, how can I programmatically distinguish between scripts and functions in MATLAB?
If I attempt to pass an argument to a script, I get Attempt to execute SCRIPT somescript as a function:. Is there a way to detect this without attempting to execute it?
Update: As #craq pointed out, shortly after this question was posted, there was an article about this on MATLAB Central: http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/
Didn't find a clean solution, but you can probably use try-catch (as #Ilya suggested) and nargin
EDIT - Use function to avoid some naming conflict; use exist to further classify the input (e.g. MEX-file)
function is_script = is_a_script( varargin )
% is_a_script( varargin ) returns one of the following:
% 1: if the input is a script
% 0: if the input is a function
% -1: if the input is neither a function nor a script.
is_script = 0;
switch( exist(varargin{1}) )
case 2
% If the input is not a MEX or DLL or MDL or build-in or P-file or variable or class or folder,
% then exist() returns 2
try
nargin(varargin{1});
catch err
% If nargin throws an error and the error message does not match the specific one for script, then the input is neither script nor function.
if( strcmp( err.message, sprintf('%s is a script.',varargin{1}) ) )
is_script = 1;
else
is_script = -1;
end
end
case {3, 4, 5, 6} % MEX or DLL-file, MDL-file, Built-in, P-file
% I am not familiar with DLL-file/MDL-file/P-file. I assume they are all considered as functions.
is_script = 0;
otherwise % Variable, Folder, Class, or other cases
is_script = -1;
end
If you are willing to use semi-documented features, here is something to try:
function tf = isfunction(fName)
t = mtree(fName, '-file');
tf = strcmp(t.root.kind, 'FUNCTION');
end
This is the same function used in MATLAB Cody and Contests to measure code length.
This is a bit of a hack, but... here is a function that will return true if the argument is a function, and false if it's not. It is possible that there are exceptions where this won't work - I look forward to comments.
EDIT - catching the case where the function is in a mex file...
function b = isFunction(fName)
% tries to determine whether the entity called 'fName'
% is a function or a script
% by looking at the file, and seeing if the first line starts with
% the key word "function"
try
w = which(fName);
% test for mex file:
mx = regexp(w, [mexext '$']);
if numel(mx)>0, b = true; return; end
% the correct thing to do... as shown by YYC
% if nargin(fName) >=0, b = true; return; end
% my original alternative:
fid = fopen(w,'r'); % open read only
while(~feof(fid))
l = fgetl(fid);
% strip everything after comment
f = strtok(l, '%');
g = strtok(f, ' ');
if strcmpi(g, 'function'), b=true; break; end
if strlen(g)>0, b=false; break; end
end
fclose(fid);
catch
fprintf(1, '%s not found!\n');
b = false;
end