MATLAB Answers

A way to work around MATLAB's inability of put a local function into M-script

조회 수: 37(최근 30일)
I have been wondering why we are not allowed to put a local function in a script file. According to related threads below, it seems that I am not the only one.
Down side of creating functions that are only to be used for a specific script might be...
  1. Names: If you keep doing this, your folder will be cluttered with lots of one-shot functions, and it is highly likely that you end up having lots of them with very similar and confusing names. Once you loose the track of record, you might not able to work out which function is right for you.
  2. Scope: Closely related to the above. Functions that are put in a folder are within the scope of all other files in the folder, or if the folder is in the MATLAB search path, of all the MATLAB files. Frequently used utility functions and those one-shot functions will be mixed up. Finding a right function may become more difficult with lots of other candidates with confusing names. Ideally, your one-shot functions should be only visible to the script that they were dedicated to.
  3. Maintenance: If you have to prepare five separate function .m files for one script, it would be more prone to loose their integrity, when copied to other place or people, for example. One-shot functions should better be kept in one place for maintenance.
I've been thinking about this, and came up with a very basic approach that can work around most of the above issues, albeit not entirely.
1. Use date-based sequential stem name for script file. A name like "scr2016_07_05_200000_xxxxx.m" may be beneficial, in that all the script and related files (html, mlx, pdf) will be shown in date order. It is easy to relate these sibling files. Also, it is useful to remember what you were up to on a specific day. Sequential numbering is a great way to avoid the pain of thinking of a unique name for just simple scripts.
2. Deploy a utility class with static methods. Create a classdef file with the name "scr2016_07_05_200000_xxxxx_util.m" Leave properties empty and put an attribute (Static) to methods as below. And then, you can add as many static functions as you want here.
classdef scr2016_07_05_200000_xxxxx_util
%scr2016_07_05_200000_xxxxx_util
properties
end
methods (Static)
function out1 = func1(var1, var2)
end
function out2 = func2(var3, varargin)
end
end
end
3. In your script, call an instance of "scr2016_07_05_200000_xxxxx_util" as below (Note you don't have to create an object to use Static methods. classname.staticMethodName(args,...) works. Below is just to avoid repeating lengthy class names.):
u = scr2016_07_05_200000_xxxxx_util;
4. Then, you can access to the static functions like this.
C = u.func1(A,B)
Benefit of this approach so far may be...
  1. Scope of those static methods are limited.
  2. You can find all of the related function in one place.
  3. You don't have to worry about thinking of absolutely unique function names every time. You only have to worry about uniqueness within the class, which is pretty easy.
  4. In essence, your script will have a twin brother of a dedicated utility class. I found that working on a .m or .mlx script and the classdef .m file side by side in one screen was extremely efficient. Your script will show abstract code on the left, and detailed workings in static methods in the classdef file on the right.
I'd like to hear your even better ideas or constructive feedback.
Thank you for reading.
Best, Kouichi
  댓글 수: 7
Guillaume
Guillaume 7 Jul 2016
This is deviating quite a lot from the original question, but anyway the way I usually cope with this sort of top level function/script that may need restarting in case of issues/crash/abort is to actually use a class. This has several advantages:
All the default constants that you would define in your scripts, they can just be the default values of the properties of your class.
If the user wants to modify some of the constants. Easy, just change the given properties.
You can save the object to a mat file, so that you have a record of the settings used without needing to modify the source code. Good for version control. You need to reprocess the data with whatever settings you used a year ago. Reload the object from the mat file.
You can have a method that starts the processing from the beginning and a similar method that resumes from where it left off.
E.g.:
classdef DropSizer < handle
properties (Access = public)
SizeThreshold = 20;
EdgeWidth = 10;
%...
end
methods
function Run(this, imagelist)
state = struct('ImageList', imagelist, 'CurrentIndex', 0);
this.Process(state);
end
function Resume(this, resumestate)
this.Process(resumestate);
end
end
methods (Access = Private)
function Process(this, state)
%processing may take a long time and crash
while state.CurrentIndex < numel(state.ImageList)
currentimage = state.ImageList(state.CurrentIndex + 1);
%entering procedure that may error
try
%do something
catch exception
fprintf(2, '<strong>While processing image index %u</strong>:\n', state.CurrentIndex + 1);
fprintf(2, '%s\n', exception.message);
assignin('base', 'resumestate', state); %store in base workspace or you could save to mat
return;
end
state.CurrentIndex = state.CurrentIndex + 1;
end
end
end
end
My functions are actually function objects which I find a lot neater when you want to deal with optional inputs (they're properties with default instead).

댓글을 달려면 로그인하십시오.

채택된 답변

Friedrich
Friedrich 7 Jul 2016
Hi,
how about giving 16b a shot? Just do it ;)
  댓글 수: 3

댓글을 달려면 로그인하십시오.

추가 답변(2개)

Steven Lord
Steven Lord 15 Sep 2016
Release R2016b is now officially available. As listed in the first item in the Language and Programming section of the Release Notes for MATLAB in that release, you can now define local functions in script files.

Kouichi C. Nakamura
Kouichi C. Nakamura 15 Aug 2016
Actually, after trying out R2016b, which allows us to use local functions in scripts or Live scripts, I still think the alternative method I proposed above has a couple of advantages over local functions.
Especially when working with Live Editor, the use of local function is rather inconvenient because Live Editor does not allow you to use graphical debug tools (break points etc). Because they are local functions, you can not access to those local functions from Command Window, either. So basically you have no way to debug the local function graphically in a Live Script.

태그

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by