I have a long anonymous function, and I wondered whether the help output can be modified (easily):
>> myfunc=#(x) x; %example anonymous function
>> help myfunc
myfunc is a variable of type function_handle.
I know long anonymous functions might be a rather unusual thing- nevertheless: can this be achieved, maybe with undocumented functions, for only as long as the function handle exists?
Edit: commenter asked for a use-case: I read up on anoynmous functions with muiltiple outputs (here Lorem on the art of matlab) such as
fmeanVar = #(x) deal(mean(x), var(x));
%a long example function to split a cell array containing 3D matrices into two cell arrays
myfunc=#(x,c) deal(cellfun(#(d) d(:,:,1:c:end),x),cellfun(#(d) d(:,:,setxor(1:c:end,1:end)),x));
And I want to make sure I remember what the second output argument is, later in time, you know... because humans forget stuff
You can create your own anonymous function handling class which would mimic this functionality, shadowing the help function for this object type only.
I've written the class below, but will show usage first, it simply requires having the class on your path and slightly adapting the way you declare anonymous functions:
We can override the subsref function for this class type also, then you can call the function handle directly using () syntax, rather than indexing into a structure as suggested by Nicky's answer.
Note that you have to pass the handle in, not the function name (i.e. help(f) or f.help, not help f or help('f')). You'd have to fully shadow the help function to get around this limitation, which I wouldn't really endorse!
Usage
>> f = anon( #() disp( 'Hi!' ), 'This function displays "Hi!"' );
>> help( f )
Input is a value of type function_handle.
This function displays "Hi!"
>> f()
Hi!
>> f = anon( #(x) x + 10, 'Adds 10 to the input' );
>> help( f )
Input is a value of type function_handle.
Adds 10 to the input
>> f(15:17)
ans =
[ 25, 26, 27 ]
>> f.func = #(x) x + 15;
>> f.helpStr = 'Adds 15 to the input'
>> f(15:17)
ans =
[ 30 31 32 ]
Default function handle help is preserved if not specified
>> f = anon( #(x) x + 10 );
>> help( f )
Input is a value of type function_handle.
Class code
The class could use some extra input checking etc, but works in principle!
classdef anon < handle
properties ( Access = public )
helpStr % String to display on help( obj )
func % Function handle (meant for anonymouse functions
end
methods
function obj = anon( func, helpStr )
assert( isa( func, 'function_handle' ) ); % Input check
obj.func = func;
if nargin > 1
obj.helpStr = helpStr; % Set help string
end
end
function help( obj )
h = help( obj.func ); % Normal behaviour.
if ~isempty( obj.helpStr )
% Custom string (does nothing if empty)
fprintf( '%s%s\n', h, obj.helpStr );
else
disp( h );
end
end
function varargout = subsref( obj, s )
% Need to override the subsref behaviour to enable default
% function calling behaviour!
switch s(1).type
case '()'
[varargout{1:nargout}] = obj.func( s(1).subs{:} );
otherwise
[varargout{1:nargout}] = builtin('subsref', obj, s);
end
end
end
end
The problem is that when you invoke help it re-reads the file. When you create an anonymous function with
f = #(x) x %Sample text
then it ignores %Sample text and is thus gone. One solution is to turn it into a struct, where one field is the function and the other the help. E.g. something like
fMeanVar.fct = #(x) [mean(x), var(x)];
fMeanVar.help = "Second output is the variance"
thus when you want to use the function you call
fMeanVar.fct([1,2,3,4])
and if you forget the usage you can simply call
fMeanVar.help
According to Matlab documentation for help, it's not possible:
help name displays the help text for the functionality specified by name, such as a function, method, class, toolbox, or variable.
Not for handle nor symbolic.
Related
I have a task to write a function that has an optional output argument.
Let's say I have a function y = fun(a,b). From what I understood, depending on whether the user needs the value y, it will EITHER calculate y OR draw some diagram.
So I think it means that if user calls my function like this: z = fun(1,2), then it calculates y and returns it, but if he calls it like this: fun(3,4);, then it won't return anything and draw a diagram instead.
Is there any way to check how my function has been called inside it? If yes, then how?
You can use nargout here:
function y = q61527462(a,b)
if nargout > 0
% Calculate y
y = a + b;
else
% Plot
plot(a,b)
end
end
so when you call the function as:
>> y = q61527462(1,2)
you get:
y =
3
and when you call with:
>> q61527462(1,2)
you get the plot
Have a look at nargout, that roughly translates to number of argument to output (there is also a nargin to check the number of input arguments).
However, the function will return the return-value anyway if your just check for nargin. You will also need to use varargout (variable argument output) to make your function return something only if the output will be assigned to some external variable.
So you just write in your function
function varargout = fun()
if nargout % implicit cast to a logical. It is equivalent to nargout > 0
% return output
varargout{1} = true; % note that this requires to wrap your output in a cell
else
% do plotting
end
EDIT:
It is even not necessary to use varargout. If you don't assign a value to a return-variable, it won't appear. So MATLAB can manage a not-assigned return-variable (something I was surprised to learn myself^^). This even works with multiple outputs!
I have a question regarding function(handles) in Octave.
So, I want to call a function, which accepts two variables and returns two(the implementation is faulty; but not relevant in this case).
According to the documentation this should be quite straightforward:
function [ret-list] = name (arg-list)
body
endfunction
I'm trying the following:
function two_d_comp = twodcomp
twodcomp.twoDperp=#perp;
^
end
function twoDperp[vmag, vangle]=perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end;
I saved the function in a file called twodcomp.m.
When I call the function as follows:
[X, Y] = twodcomp.twoDperp(1,2)
Octave spits out the following:
error: #perp: no function and no method found
error: called from
twodcomp at line 2 column 20
I managed to remove the error by removing the output arguments vmag and vangle, as follows:
function twoDperp=perp(x,y)
But this is obviously not really what I want.
Do you guys happen to have some pointers as to what I'm doing wrong?
Cheers
Your initial function twodcomp: you cannot have the output variable (before the =) be named the same as your function name (after the =).
Then if you want to assign an anonymous function (MATLAB docs, Octave docs) using the # notation, you can still pass the desired inputs.
So rewrite it like:
% Include empty parentheses after a function name to make it clear which is the output
function output = twodcomp()
% Not sure why you're assigning this function to a struct, but
% still give yourself the ability to pass arguments.
% I'm assuming you want to use the output variable,
% and not reuse the main function name (again)
output.twoDperp = #(x,y) perp(x,y);
end
With your second function, you just need to remove the twoDperp before your output arguments. In your question you state the expected syntax from the docs, but then didn't follow it...
function [vmag, vangle] = perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end
Now these can be used like so:
% Deliberately using different variable names to make it clear where things
% overlap from the function output. twodcomp output is some struct.
myStruct = twodcomp();
% The output struct has the field "twoDperp" which is a function with 2 outputs
[m, a] = myStruct.twoDperp(1,2);
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.
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').
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.