- If the one-shot function is not that complicated, then you could always use an anonymous one.
- You always have the alternative of making the script a function. It's just an extra line. There's no big difference between them and you can put as many one-shot functions inside it as you'd like.
A way to work around MATLAB's inability of put a local function into M-script
    9 visualizaciones (últimos 30 días)
  
       Mostrar comentarios más antiguos
    
    Kouichi C. Nakamura
      
 el 6 de Jul. de 2016
  
    
    
    
    
    Comentada: Kouichi C. Nakamura
      
 el 15 de Sept. de 2016
            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...
- 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.
- 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.
- 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...
- Scope of those static methods are limited.
- You can find all of the related function in one place.
- 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.
- 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 comentarios
  Guillaume
      
      
 el 7 de Jul. de 2016
				
      Editada: Guillaume
      
      
 el 7 de Jul. de 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).
Respuesta aceptada
  Friedrich
    
 el 7 de Jul. de 2016
        Hi,
how about giving 16b a shot? Just do it ;)
3 comentarios
  Guillaume
      
      
 el 7 de Jul. de 2016
				I would have thought the first thing you'd do on downloading the pre-release is to look at the release note to see what's new.
It's the first entry under Language and Programming.
Más respuestas (2)
  Steven Lord
    
      
 el 15 de Sept. de 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.
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




