Reputation: 73
What I have:
I have a matlab script called myscript.m
which uses the p-coded helper functions fcn_A.p
and fcn_B.p
(which I wrote and have the source code for).
What I want:
I'd like to distribute those to others as a single unit such that:
>> myscript
>> myscript
runs a script - not a function. I.e. variables it defines are set in the matlab base environmentAs far as possible, I'd also like to avoid protecting myscript
. That way, it can be used as an example of how to use fcn_A
and fcn_B
.
Edit: Optimally, I'd like a file or folder that you just move into your path or working directory and then it all works, without even changing the path.
What I tried:
Putting everything into the same script file doesn't fulfill the second requirement.
Making it a class (either through a classdef
file or a @myscript
directory) doesn't fulfill the third requirement.
Making it a package (using a +myscript
directory) doesn't fulfill the first requirement.
What I believe I need
I believe this could be solved if there was a way to define a 'default' function of a package. Kind of like how the contents of +mypackage/Contents.m
is displayed when you type help mypackage
.
Is there a way to do this?
Upvotes: 1
Views: 178
Reputation: 73
It turns out that all of my requirements can in fact be fulfilled by a class by using assignin
.
My solution would look like this:
Files:
@myscript
@myscript/myscript.m
@myscript/fcn_A.p
@myscript/fnc_B.p
@myscript/myscript.m
classdef myscript
methods (Static)
fcn_A
fcn_B
end
methods
function self = myscript()
% Using a variable defined in the calling environment (if defined)
outside_variable = evalin('caller', 'outside_variable', NaN);
if isnan(outside_variable)
outside_variable = 'default value';
end
... code goes here ...
outside_variable = self.fcn_A(parameters, outside_variable);
% Putting the variable back in the calling environment (even if not defined before)
assignin('caller', 'outside_variable', outside_variable);
end
end
end
Now:
>> myscript
will run the class constructor and return an
empty class object, which I can just ignore.myscript.fcn_A
and myscript.fcn_B
can be called since they are static class functions.variable_to_save
will be set in the base environment as expected.@myscript
directory into the path at a new computer is enough to make it work.There is one remaining problem, though.
If fcn_A
or fcn_B
is a class, this will not work, since MATLAB doesn't allow stacked classes. Bummer! I did not mention this in the question, because I couldn't imagine it would make a difference...
Upvotes: 1
Reputation: 4477
You cannot have myscript as a script if you want a single file solution. But if the purpose of myscript is only for providing example usage and assigning output in base workspace you can achieve this using a function or class.
With a function you can put all the usage as a string and then display the string when myscript is called with no arguments or some special argument like '-help'. You can assign the outputs from myscript in the base workspace using assignin. For example,
function myscript(varargin)
if nargin == 0
disp('Usage: myscript(fcn_a...');
return;
end
if strcmp(varargin{1}, 'A')
y = fcn_A(varargin{2:end});
else
y = fcn_B(varargin{2:end});
end
assignin('base','y',y);
end
function y = fcn_A(varargin)
y = 1;
end
function y = fcn_B(varargin)
y = 2;
end
Now you can p-code this entire function in one file. You can do a similar setup with a class. There it might be better to show the usage using a disp method and then provide fcn_A and fcn_B as static methods of the class.
Upvotes: 1
Reputation: 21563
The way I (and mathworks) would typically do this:
Now you just have 1 file for distribution, perhaps even including documentation
Note that this is actually what matlab itself does. See this link for example:
Ismemberf on matlab file exchange
Upvotes: 1
Reputation:
Add the folder that holds your functions and script to the MATLAB path. Fulfills all 4 conditions.
Upvotes: 1