`localfunctions` inside a package - matlab

localfunctions returns function handles to all the local functions in an m-file. However, this doesn't work in a package. For example, the following code saved as 'a.m' runs fine:
function fs = a()
fs = localfunctions;
end
function babo()
end
function hidden()
end
Called from MATLAB console:
>> a()
ans =
#babo
#hidden
But when it is inside a package as '+aaa/b.m', I get nothing:
>> aaa.b()
ans =
{}
I don't think this behavior is well documented. How do I overcome this?
I need to use localfunctions to unit test some functions within the package and I don't want to keep it outside of the package just because of this.

One solution would be to import the package before calling localfunctions:
+mypkg/mytest.m
function f = mytest()
import mypkg.*
f = localfunctions;
end
function foo()
end
function bar()
end
When called:
>> f = mypkg.mytest()
f =
#foo
#bar
>> functions(f{1})
ans =
function: 'foo'
type: 'scopedfunction'
file: 'C:\Users\Amro\Desktop\+mypkg\mytest.m'
parentage: {'foo' 'mytest'}

There is a bug in R2013b and R2014a where localfunctions does not respect the package of the file containing the local functions. This bug has been reported to The MathWorks for fixing in a future release.
Until then, Amro's workaround is the best option.
EDIT: This has been fixed in release R2014b.

Related

Getting the full path of the function calling the constructor

I'd like the constructor of a class to automatically determine the full path to the calling function, so that that class can write a file that's guaranteed to be in the caller's directory (instead of whatever happens to be the pwd()).
So, I have the following setup:
In some_path/test.m:
function test
SomeClass()
end
In some_path/some_subdir/SomeClass.m:
classdef SomeClass < handle
methods
function obj = SomeClass()
evalin('caller', 'mfilename(''fullpath'')')
end
end
end
When I call test(), I get the following:
>> test()
ans =
'some_path/some_subdir/SomeClass.m' % <- ...why?
I expected the call to mfilename() in evalin('caller', ...) to evaluate inside test(), but apparently, that doesn't happen...
Nesting evalins doesn't seem to help:
...
function obj = SomeClass()
evalin('caller', ' evalin(''caller'', ''mfilename(''''fullpath'''')'') ')
end
...
>> test()
ans =
'some_path/some_subdir/SomeClass.m'
The only way to get this to work is the far less intuitive dbstack():
...
function obj = SomeClass()
S = dbstack(1, '-completenames');
S(1).file
end
...
>> test()
ans =
'some_path/test.m'
What am I missing?
It looks like you cannot use evelin for this purpose. From the documentation:
evalin('caller', expression) finds only variables in the caller's workspace; it does not find functions in the caller.
From that I read that not the full context of the calling function is recovered before evaluating the expression, only variables in the workspace of the calling function are made available.
That same documentation page also mentions this limitation:
evalin cannot be used recursively to evaluate an expression. For example, a sequence of the form evalin('caller', 'evalin(''caller'', ''x'')') doesn't work.
That is consistent with the notion that only the caller's workspace is made available, not the full context. The expression is not actually evaluated as if it were written inside the calling function.
I have repeated your experiment with a simple M-file function, just to verify this indeed is not specific to classes or constructors, but generally applies to any function, anywhere.
The dbstack option is the way to go.

Why does Matlab's cellfun function not honor imports? How to propagate import statement to anonymous functions?

I want to test a cell array of objects for objects of a certain class.
I organize my files in packages and use import statements to make my code shorter.
The problem: cellfun(#(o) isa(o,'MyClassName'),myCellArray) seems to ignore the import declaration, returning false for cell array elements where invoking isa(myCellArray{i}, 'MyClassName') would yield true.
How can I make cellfun honor my import statements?
EDIT: Might the import statement not propagate to the anonymous function inside cellfun? If yes, how can I archieve this?
Minimal (Not) Working Example
Files:
myfun.m
+pkg/
+pkg/MyClass.m
myfun.m:
% cat <<"%EOF" > myfun.m # paste into shell if on UNIX
function myfun()
import pkg.MyClass;
o{1} = MyClass();
x = cellfun(#(d) isa(d,'MyClass'),o);
fprintf('cellfun: %d\n',x);
b = isa(o{1},'MyClass');
fprintf('direct: %d\n',b);
fprintf('classes of o: \n');
cellfun(#class, o,'UniformOutput',false)
end
%EOF
+pkg/MyClass.m:
% mkdir "+pkg"; cat <<"%EOF" >"+pkg/MyClass.m" # paste to shell if on UNIX
classdef MyClass
end
%EOF
My Output is:
>> myfun
cellfun: 0
direct: 1
classes of o:
ans =
'pkg.MyClass'
If I move MyClass.m to the same directory as myfun.m and remove the import ... line in myfun.m:
>> myfun
cellfun: 1
direct: 1
classes of o:
ans =
'MyClass'
>>

using evalin to evaluate a function in the base workspace

I am trying to allow a function to have access to the base workspace using the evalin function, but I am having trouble. Here is a simple example:
My main code:
A = 1;
B = 2
evalin('base','[ C ] = FUN(B)');
C
My Function:
function [C ] = FUN( B )
C = A + B;
end
My error:
Undefined function or variable 'A'.
Error in FUN (line 4)
C = A + B;
Error in Test (line 4)
evalin('base','[ C ] = FUN(B)');
So, the function is not being evaluated in the base workspace because it does not know what the value of A is.
Can anyone suggest something? I have a lot of variables that I need to access in several functions and I don't want to pass them and I don't want to use global variables.
Thanks!
From the evalin documentation,
evalin(ws, expression) executes expression, a string containing any valid MATLABĀ® expression, in the context of the workspace ws. ws can have a value of 'base' or 'caller' to denote the MATLAB base workspace or the workspace of the caller function.
So the line of code
evalin('base','[ C ] = FUN(B)');
evaluates only the line of code
[ C ] = FUN(B)
in the context of the base workspace. It does not evaluate the body of the function within the context of the base workspace. So the error that you are observing makes sense.
Is there a particular reason why you don't want to pass the variables in to the function? Why do you have several variables in the base (?) workspace, or do you just have several variables within a main function?
If the latter, you could use nested functions to have access to the variables declared in the caller (function) workspace. For example, suppose you have a main function like
function main()
A = 1;
B = 2;
C = FUN();
function [C] = FUN()
C = A + B;
end
end
The function FUN has access to both A and B and so you don't have to pass in any arguments.
An alternative to passing in several different inputs, is to just pass in a structure that has different fields that your function can access at will. Using the above example, we could do the following
function main()
A = 1;
B = 2;
data.A = A;
data.B = B;
C = FUN(data);
end
function [C] = FUN(data)
C = data.A + data.B;
end
In this case, the function FUN can be a function within its own file or declared after main. Again, we only pass in one argument that has all the data that the function needed.
Actually Evalin function is used to take data from base workspace:
Syntax is :
evalin('base','variable')
Evalin function is used in the function .
For example see the below function
function [out1 out2 out3]=main_fun(in1,in2)
out1=in1+in2;
out2=in1-in2;
in3=evalin('base','in3');
in4=evalin('base','in4');
out3=in3+in4;
end
Here out3 value will have the sum of in3 and in4 from workspace.
out1 and out2 will have the sum and difference of in1 and in2 from current function workspace.

Anonymous function inside a script error

I created an anonymous function inside a script and I can't get MATLAB to run the fminsearch? Here's an what I have so far:
V=x(1);
f=x(2);
q=#(x) (pi.*D.*L)./(1000.*V.*f);
fminsearch(#q,x);
The variables D and L are defined, but MATLAB gives me the following error:
Error: File: Testing.m Line: 51 Column: 17
"q" was previously used as a variable, conflicting with its use here as the name of a function or command.
See "How MATLAB Recognizes Command Syntax" in the MATLAB documentation for details.
q is not mentioned before this command. What am I doing wrong?
Another thing that could solve my problem is to get my script to write a function file, but how to do that?
Remove the second #:
V=x(1);
f=x(2);
q=#(x) (pi.*D.*L)./(1000.*V.*f);
fminsearch(q,x);
q is a function handle. fminsearch expects a function handle. You can create a function handle out of a function using an # (e.g. #min), but you don't need to do that here.
You can also write the anonymous function inline with the search command:
V=x(1);
f=x(2);
fminsearch(#(x) (pi.*D.*L)./(1000.*V.*f),x);
UPDATE (credits to #wakjah)
For your code to do anything sensible, you should use the argument x of the anonymous function:
x0 = [initialV, initialF];
fminsearch(#(x) (pi.*D.*L)./(1000.*x(1).*x(2)), x0);
#function creates a function handle for an existing function.
q = #(x) whatever... creates a function handle called q.
But, you can't create a function handle for a function handle, only for a function.
See this:
>> fones = #ones
fones =
#ones
>> ffones = #fones
Error: "fones" was previously used as a
variable,
conflicting with its use here as the name
of a function or command.
See MATLAB Programming, "How MATLAB
Recognizes Function Calls That Use
Command Syntax" for details.
In Matlab, a function handle is a kind of a pointer to a function and is distinct from a function (unlike in some other languages where the a function identifier can be passed and stored as any other variable).
It's important to note that calling a function and a function handle results in the same behaviour. Except for the case where the identifier is used without any parentheses following it:
>> ones
ans =
1
>> fones
fones =
#ones
>> ones(2)
ans =
1 1
1 1
>> fones(2)
ans =
1 1
1 1

Is it possible to hide the methods inherited from the handle class in matlab?

I'm working on a command line application for ultrasound simulation in MATLAB. Nearly every object in our code is a subclass of handle (to pass as references). The problem I'm having is that all the methods inherited from the handle class shows up under the "Methods" section in MATLAB (see example below).
What I want is to hide the inherited methods from the handle class so that only the function the user is allowed to use is shown under "Methods". This way it doesn't look so messy for the user if he/she wants to know which methods to use.
Example Test class:
classdef Test < handle
methods
function myFunction(obj)
end
end
end
In the command line:
T = Test()
T =
Test handle with no properties.
Methods, Events, Superclasses
After clicking on "Methods":
Methods for class Test:
Test delete findobj ge isvalid lt ne
addlistener eq findprop gt le myFunction notify
What I want:
Methods for class Test:
Test myFunction
Is this possible in MATLAB?
If you overload all of the subclass methods in a hidden methods block I think it will do exactly what you're looking for.
I'm not sure which versions of Matlab this works in, but it definitely works for me in R2012b.
The exception is isvalid as it is Sealed so you can't override it in a handle subclass.
classdef handle_light < handle
methods(Hidden)
function lh = addlistener(varargin)
lh = addlistener#handle(varargin{:});
end
function notify(varargin)
notify#handle(varargin{:});
end
function delete(varargin)
delete#handle(varargin{:});
end
function Hmatch = findobj(varargin)
Hmatch = findobj#handle(varargin{:});
end
function p = findprop(varargin)
p = findprop#handle(varargin{:});
end
function TF = eq(varargin)
TF = eq#handle(varargin{:});
end
function TF = ne(varargin)
TF = ne#handle(varargin{:});
end
function TF = lt(varargin)
TF = lt#handle(varargin{:});
end
function TF = le(varargin)
TF = le#handle(varargin{:});
end
function TF = gt(varargin)
TF = gt#handle(varargin{:});
end
function TF = ge(varargin)
TF = ge#handle(varargin{:});
end
function TF = isvalid(varargin)
TF = isvalid#handle(varargin{:});
end
end
end
If you save the above class to handle_light.m and then type methods handle_light in the command window you will get the following result:
Methods for class handle_light:
handle_light isvalid
The Test class then becomes:
classdef Test < handle_light
methods
function myFunction(obj)
end
end
end
Doing it in this way means that you don't need to put the overloads in the Test class which keeps things neater.
There is a solution here, including sample code.
In short, what you need to do is to overload Matlab's built-in function methods, so that when it is called on your class, it removes the methods of handle from the output. Make sure it works on everything else, though so that you don't mess up your user's other code. If you don't use the #foldername variant to store your class, you could put it into a private directory, for example.
Not a full solution, but if you do methods(T, '-full'), then it at least tells you which methods are inherited from handle, so you know what to ignore.
Just get the functions from the inherited class and cancel them out with the ones from the main class using setdiff.
mH = methods('handle');
m = methods('MyClass');
m = setdiff(m,mH);