How to implement an "importable namespace"? - matlab

I know that I can use a class consisting solely of static methods to implement a namespace in MATLAB. E.g.
classdef MyNamespace
methods (Static = true)
function [...] = foo(...)
...
end
function [...] = bar(...)
...
end
...
end
end
With the above I can call functions MyNamespace.foo, MyNamespace.bar, etc. (assuming, of course, that the file MyNamespace.m is in my search path, or in the current directory).
A paramount feature of this technique is that it allows simulating "namespace variables". For example, a function within the methods (Static = true) could have the form
function out = BAZ(newval)
persistent val;
out = val;
if nargin > 0, val = newval; end
end
With this, the method MyNamespace.BAZ can mimic a "namespace variable" MyNamespace.BAZ (though, admittedly, in a very cumbersome way).
This feature is one that I absolutely require.
The implementation of namespaces described above is ok, but I'd like to be able import namespace, so that I can call their functions using their "short" (aka "unqualified") names, such as foo, bar, etc.
How can I implement a namespace that can be imported, in the sense described above?
BTW, I'd prefer answers that build on the technique illustrated above (for implementing namespaces), since it's a technique I have some experience with, but I'm also open to alternatives that are not based on this technique.

MATLAB has a package system which allows creating a namespace of functions which are also importable. In short, just drop a directory whose name begins with a + in another directory on your path and add your function MATLAB files in that directory. If you have MyNamespace.m in the directory someDir then just create:
someDir/+MyNamespace/foo.m
someDir/+MyNamespace/bar.m
and so on. You can call them via MyNamespace.foo, MyNamespace.bar and import them:
import MyNamespace.foo
or:
import MyNamespace.*

Related

Using unittest with own matlab toolbox

I inherited a code base in matlab, which I like to put under unittest with the matlab.unittest framework.
To make the code base more robust against arbitrary addpath of my users, I have put most of the code into +folders like a toolbox. So the general layout is:
+folder1/file1.m
+folder1/runtestsuite.m
+folder1/unittest_data/file1_testdata.mat
+folder1/+folder2/file2.m
+folder1/+folder2/unittest_data/file2_testdata.mat
...
and updated all internal references with the correct import statements.
Now, I like to add a unittest for file1.m. However if I put a file in +folder1/file1_test.m file1.m seems not to be visible.
Here is my example code of file1_test.m
classdef file1_test < matlab.unittest.TestCase
properties
path
end
methods(TestMethodSetup)
function setunittestdatapath(testCase)
p = mfilename('fullpath');
[directory,~,~]=fileparts(p);
testCase.path = fullfile(directory,'unittest_data');
end
end
methods (Test)
function file1_input(testCase)
%import folder1.file1
testdata = load(fullfile(testCase.path),'file1_testdata.mat');
result = file1(testdata.input);
testCase.verifyEqual(result, testdata.output);
end
end
end
If I uncomment the import statement the unittest works fine. So currently I have to add all import statements to each individual test, which I like to avoid. Is there a more elegant way for doing something like this?
I tried importing it at the beginning of the file, although matlab complains "Parse error at CLASSDEF: usage might be invalid MATLAB syntax." this also works. So what is the correct and most pragmatically way for doing something like this?
import statements only apply to the local scope of where they are used so if you want a function to be able to not use the full-qualified name, then you'll have to add the import statement to each function separately.
The import list scope is defined as follows:
Script invoked from the MATLAB® command prompt — Scope is the base MATLAB workspace.
Function, including nested and local function — Scope is the function and the function does not share the import list of the parent function. If the import list is needed in a MATLAB function or script and in any local functions, you must call the import function for each function.
For unit tests though, I would argue that it is probably best to use the fully-qualified function name every time (rather than relying on import) so that it's clear to the user what you're testing.
result = folder1.file1(testdata.input)
Currently import statements in MATLAB have function scope as mentioned in the answer by Suever.
However, I often use local functions as a workaround to mimic a file level import:
classdef file1_test < matlab.unittest.TestCase
properties
path
end
methods(TestMethodSetup)
function setunittestdatapath(testCase)
p = mfilename('fullpath');
[directory,~,~]=fileparts(p);
testCase.path = fullfile(directory,'unittest_data');
end
end
methods (Test)
function file1_input(testCase)
%import folder1.file1
testdata = load(fullfile(testCase.path),'file1_testdata.mat');
result = file1(testdata.input);
testCase.verifyThat(result, IsEqualTo(testdata.output));
end
end
end
% Include file level "import" functions below
function f = file1(varargin)
f = folder1.file1(varargin{:});
end
function c = IsEqualTo(varargin)
c = matlab.unittest.constraints.IsEqualTo(varargin{:});
end
Note in this example I "imported" both your source code as well as some of the test framework source code in order to use the literate form of verifyEqual using verifyThat. Note this is the same functional behavior, but in general there exists more functionality with the constraints than with the qualification methods so this may be helpful to you at some point.

How to make internal/helper functions testable?

Suppose that I have some function Foo that uses two internal helper functions bar and baz.
Is there a way to organize the code so that bar and baz remain "out of sight", but at the same time can be unit-tested? (Preferably, the unit tests for bar and baz would be in the same suite as the unit tests for the main function Foo.)
There are a few options to achieve this.
First, does Foo need to be a function? If it is a class then you can implement bar and baz as Hidden and Access='protected' which is pretty tightly locked down. Then you can create a test specific subclass that accesses bar and baz for testing. You can also scope the access to the test to further lock it from others view if desired.
If you do want Foo to be a function then you still have options. One of those is to somehow get a function handle to the private local functions to your tests. You can do this through some special calling syntax of Foo that returns these functions to a test when called. This however, modifies the production code in a potentially confusing way, and it essentially inserts test logic into production. I would prefer hiding these functions by putting them into a package so that they are not in the global namespace. The name of the package can indicate that they are off limits and not part of your supported interface.
Finally, one option is to simply use the public interface in order to test these functions. Clearly they are called from the function in some scenario. You may want to consider writing a test through the front door of your interface. One benefit of this is that you would then be able to change the implementation of your local function structure easily without modifying your test. The private functions are private because by definition they are part of your implementation, not your interface. If you find it complex enough to require its own test independent from the interface of Foo then it should probably just be broken out into another package function or class as described above in order to unit test it.
Not the most elegant way to do it but then Matlab is not the most practical language to build modules in a single code file.
One way to do it is to have a higher level level function which transfer the input arguments to the function you choose:
function out = fooModule( FunctionCalled , varargin)
%// This main function only transfer the input argument to the function chosen
switch FunctionCalled
case 'main'
out = foo(varargin) ;
case 'bar'
out = mBar(varargin) ;
case 'baz'
out = mBaz(varargin) ;
end
end
function outFoo = foo(varargin)
%// your main FOO code
%// which can call the helper function if necessary
end
function outbar = mBar(varargin)
%// your code
end
function outbaz = mBaz(varargin)
%// your code
end
You can even embed the FunctionCalled parameter into varargin if you want to compact things. This would also allow to test the type of the first argument. So for example if the first argument is not a string (calling one of the helper function) then forward the execution directly to the main foo function without having to call it explicitly (so the helper functions remain 'out of sight' if not called explicitly).
Otherwise, a completely different approach, you could consider writing a class.

Matlab defining class functions in an elegant way for OOP

I am trying to implement a small example function in Matlab OOP.
The functioning code is:
classdef Cat < handle
properties
meowCount = 0;
end
methods
function obj = Cat() % all initializations, calls to base class, etc. here,
end
function Meow(obj)
disp('meowww');
obj.meowCount = obj.meowCount + 1;
end
end
end
I want to create something of the following sort akin to C++ as my real life function definitions are very big and I don't want to clutter my class definition:
classdef Cat < handle
properties
meowCount = 0;
end
methods
function obj = Cat() % all initializations, calls to base class, etc. here,
end
function Meow(obj);
end
end
%%
function Cat::Meow(obj)
disp('meowww');
obj.meowCount = obj.meowCount + 1;
end
So, basically write the definition of function Meow outside the class. How do I accomplish the above change ?
To play with the working first version you can use the following:
C = Cat;
C.meowCount
C.Meow
Create a folder called #Cat.
The within #Cat, put the following files:
Cat.m
classdef Cat < handle
properties
meowCount = 0;
end
methods
function obj = Cat()
end
Meow(obj) % this is optional, and just indicates the function signature
end
end
Meow.m
function Meow(obj)
disp('meowww');
obj.meowCount = obj.meowCount + 1;
end
Move out of the #Cat folder, and make sure it (or its parent folder) is on your path. Then try your examples.
If you use an # folder to contain your class like this, most methods (though not constructors, and not property get/set methods) can be moved to external files.
If you want, you can include a function signature with no implementation in the main classdef file. This is sometimes optional, but if you wish to change the Access level of the method away from default, it is necessary.
There are two ways of defining methods of a class. The newer, more portable way, is by defining them within the same classdef file. You can also write methods as separate M-file functions and put them in a #MyClass folder. Note that some methods must be in the classdef file. You can still define your separate file methods as static and private via helper functions. This is a bit of hack, which is why it's a good idea to put everything in the classdef file unless you have a very large project.
The best way to deal with clutter in your classdef file is to use code-folding. You can collapse individual methods and entire method blocks. In this way you can easily organize your classdef file to be as uncluttered as possible by grouping related methods together in the same methods block. Collapse any methods/blocks you aren't using at the time.
Additionally, you can use the "Go To" button in the Editor Ribbon Tab to select a specific method to view (if they are all defined in the same file).
Writing your methods in separate files may seem like a good solution at first, but if you have a class with many methods, it becomes extremely cumbersome to have many files open at once. Unlike C++, you can only define one method per file. It really ends up being quite a mess.
See Also:
Code Folding — Expand and Collapse Code Constructs
Editor/Debugger Code Folding Preferences

#folder and +folder

What is the meaning of the following folder names in MATLAB?
#folder
+folder
I've created a class Tata.m which uses the classdef syntax.
Should I put it in an #folder or a +folder?
I've looked at the documentation but it is not really clear
in which cases the #folder should be used and in which cases the +folder should be used.
The +folder piece is a MATLAB package folder. If you place Tata.m in a location like +folder/Tata.m, it will be known to MATLAB as the class folder.Tata. If you place it in a folder like someOtherFolder/Tata.m, or someOtherFolder/#Tata/Tata.m, it will be known to MATLAB as Tata.
It can be useful to place a classdef file in a class directory like #Tata to allow you to put the definition of some (or all) methods in separate files.
The doc has more details.
EDIT: To attempt to clarify the # directories: historically, a class Tata with methods methodOne and methodTwo would require the following files:
somePlaceOnThePath/#Tata/Tata.m
somePlaceOnThePath/#Tata/methodOne.m
somePlaceOnThePath/#Tata/methodTwo.m
In the "new" object system, you can still use the layout above without modification. At the other extreme, you can place the entire implementation of Tata in a single classdef block in:
somePlaceOnThePath/Tata.m
If you have some large methods, or want to split up the implementation of the class Tata into several files to make parallel development simpler, you can take use a classdef like this:
%# somePlaceOnThePath/#Tata/Tata.m:
classdef Tata
methods
result = methodTwo(obj, arg)
function methodOne(obj)
disp('hello from methodOne');
end
end
end
And also
%# somePlaceOnThePath/#Tata/methodTwo.m:
function result = methodTwo(obj, arg)
% do stuff with obj and arg
end
Strictly speaking, the advance declaration of methodTwo in the classdef is optional because it's using the default access specifiers. If you wanted to have methodTwo be a private method, you could place it in a methods (Access = private) block.

Is self-reference possible in MATLAB?

As noted here, functions in packages, as well as static methods in classes, still need to use a packagename.functionname syntax or import packagename.* for each function (since the imports are part of the function workspace and not global). This means that changing the package/class name later on can become a tedious nuisance.
Is there any way to do something like import this.*, i.e. a package/class name agnostic method to access all functions/static methods in the same package/class?
So... doesn't this require importthis to also be imported? Or is importthis a function you always have in your path?
It seems hardly more complex to just paste an "import this" block with this at the top of each function, and then you don't have to worry about importthis being in your path. I tend to feel that reliance on path is dangerous.
"Import This" block
%% Import own package
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end) '.*']);
You can even put it in a try/catch block to make sure it's in a package directory, and decide what to do if it's not.
%% Import own package
try
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end)'.*']);
catch err
if ~strcmp(err.identifier,'MATLAB:UndefinedFunction'), rethrow(err); end
end
I recently ran into a similar problem and found the following solution for packages. However it is VERY hacky.
You create a function called import this with an optional argument.
function to_eval = importthis(exclude_list)
if nargin == 0
exclude_list = [];
end
var_name = genvarname('A', exclude_list); %avoid shadowing
to_eval = ['[~,'...
, var_name...
, ']=fileparts(fileparts(mfilename(''fullpath'')));'... %get containing dir
, 'eval([''import '','...
, var_name...
, '(2:end),''.*'']);'... %remove '+'
, 'clear '... %clean up
, var_name
];
end
This function returns a string which can then be evaled that imports the "this" package. So in your package functions you would put the following near the top:
function B = myfunc(A)
eval(importthis);
%function body
end
You can also pass who to importhis, leaving your function's namespace clean.
function B = myfunc(A)
eval(importthis(who));
%function body
end
I can't decide whether I should feel proud or discusted by what I did.
This probably is not a bounty worthy answer but as you do not have any answers I thought I would post it anyway! You can invoke static methods via an instance of the class which you would only need to define once. You can invoke functions via a function handle but this would require one handle per function.
Using these techniques you could define all your static method and function references in one place. Then you would use these references throughout your package. Then if you decided to change the package name at a later point you would only need to update these references which are all stored in one place.
See:
Calling Static Methods
You can also invoke static methods using an instance of the class,
like any method:
obj = MyClass;
value = obj.pi(.001);
function_handle (#)
The following example creates a function handle for the humps function
and assigns it to the variable fhandle.
fhandle = #humps;