Is it possible to define more than one function per file in MATLAB, and access them from outside that file?
Asked Answered
C

9

227

When I was studying for my undergraduate degree in EE, MATLAB required each function to be defined in its own file, even if it was a one-liner.

I'm studying for a graduate degree now, and I have to write a project in MATLAB. Is this still a requirement for newer versions of MATLAB?

If it is possible to put more than one function in a file, are there any restrictions to this? For instance, can all the functions in the file be accessed from outside the file, or only the function that has the same name as the file?

Note: I am using MATLAB release R2007b.

Churrigueresque answered 25/8, 2010 at 20:26 Comment(0)
P
279

The first function in an m-file (i.e. the main function), is invoked when that m-file is called. It is not required that the main function have the same name as the m-file, but for clarity it should. When the function and file name differ, the file name must be used to call the main function.

All subsequent functions in the m-file, called local functions (or "subfunctions" in the older terminology), can only be called by the main function and other local functions in that m-file. Functions in other m-files can not call them. Starting in R2016b, you can add local functions to scripts as well, although the scoping behavior is still the same (i.e. they can only be called from within the script).

In addition, you can also declare functions within other functions. These are called nested functions, and these can only be called from within the function they are nested. They can also have access to variables in functions in which they are nested, which makes them quite useful albeit slightly tricky to work with.

More food for thought...

There are some ways around the normal function scoping behavior outlined above, such as passing function handles as output arguments as mentioned in the answers from SCFrench and Jonas (which, starting in R2013b, is facilitated by the localfunctions function). However, I wouldn't suggest making it a habit of resorting to such tricks, as there are likely much better options for organizing your functions and files.

For example, let's say you have a main function A in an m-file A.m, along with local functions D, E, and F. Now let's say you have two other related functions B and C in m-files B.m and C.m, respectively, that you also want to be able to call D, E, and F. Here are some options you have:

  • Put D, E, and F each in their own separate m-files, allowing any other function to call them. The downside is that the scope of these functions is large and isn't restricted to just A, B, and C, but the upside is that this is quite simple.

  • Create a defineMyFunctions m-file (like in Jonas' example) with D, E, and F as local functions and a main function that simply returns function handles to them. This allows you to keep D, E, and F in the same file, but it doesn't do anything regarding the scope of these functions since any function that can call defineMyFunctions can invoke them. You also then have to worry about passing the function handles around as arguments to make sure you have them where you need them.

  • Copy D, E and F into B.m and C.m as local functions. This limits the scope of their usage to just A, B, and C, but makes updating and maintenance of your code a nightmare because you have three copies of the same code in different places.

  • Use private functions! If you have A, B, and C in the same directory, you can create a subdirectory called private and place D, E, and F in there, each as a separate m-file. This limits their scope so they can only be called by functions in the directory immediately above (i.e. A, B, and C) and keeps them together in the same place (but still different m-files):

    myDirectory/
        A.m
        B.m
        C.m
        private/
            D.m
            E.m
            F.m
    

All this goes somewhat outside the scope of your question, and is probably more detail than you need, but I thought it might be good to touch upon the more general concern of organizing all of your m-files. ;)

Perjury answered 25/8, 2010 at 20:28 Comment(2)
The favorite answer option looks like this ^, @idigasPartisan
@Partisan I assume he meant along the lines of favouriting a question, which can be up-voted independently of favouriting.Pomfrey
D
84

Generally, the answer to your question is no, you cannot define more than one externally visible function per file. You can return function handles to local functions, though, and a convenient way to do so is to make them fields of a struct. Here is an example:

function funs = makefuns
  funs.fun1=@fun1;
  funs.fun2=@fun2;
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

And here is how it could be used:

>> myfuns = makefuns;
>> myfuns.fun1(5)    
ans =
     5
>> myfuns.fun2()     
ans =
     1
Disobedient answered 26/8, 2010 at 1:15 Comment(0)
M
38

The only way to have multiple, separately accessible functions in a single file is to define STATIC METHODS using object-oriented programming. You'd access the function as myClass.static1(), myClass.static2() etc.

OOP functionality is only officially supported since R2008a, so unless you want to use the old, undocumented OOP syntax, the answer for you is no, as explained by @gnovice.

EDIT

One more way to define multiple functions inside a file that are accessible from the outside is to create a function that returns multiple function handles. In other words, you'd call your defining function as [fun1,fun2,fun3]=defineMyFunctions, after which you could use out1=fun1(inputs) etc.

Marshallmarshallese answered 25/8, 2010 at 20:37 Comment(2)
I would not use oop for this purpose, it adds a substantial overhead especially for static methods. (#1693929)Longplaying
@Daniel: The overhead is noticeable only if you do a huge amount of function calls and the calculations in the method is quasi-instantaneous. Both conditions often point to bad design - no vectorization, and meaningless functions. Thus, i wouldn't be too worried.Marshallmarshallese
A
24

I really like SCFrench's answer - I would like to point out that it can easily be modified to import the functions directly to the workspace using the assignin function. (Doing it like this reminds me a lot of Python's "import x from y" way of doing things)

function message = makefuns
  assignin('base','fun1',@fun1);
  assignin('base','fun2',@fun2);
  message='Done importing functions to workspace';
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

And then used thusly:

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1
Amphibole answered 1/6, 2013 at 6:59 Comment(1)
assignin('caller',...) would be more correct. You might want to use these functions from within another function.Donaghue
D
12

Along the same lines as SCFrench's answer, but with a more C# style spin..

I would (and often do) make a class containing multiple static methods. For example:

classdef Statistics

    methods(Static)
        function val = MyMean(data)
            val = mean(data);
        end

        function val = MyStd(data)
            val = std(data);
        end
    end

end

As the methods are static you don't need to instansiate the class. You call the functions as follows:

data = 1:10;

mean = Statistics.MyMean(data);
std = Statistics.MyStd(data);     
Dysgenics answered 31/7, 2014 at 9:35 Comment(0)
G
4

I define multiple functions in one .m file with Octave and then use the command from within the .m file where I need to make use of the functions from that file:

source("mycode.m");

Not sure if this is available with Matlab.

octave:8> help source
'source' is a built-in function

 -- Built-in Function:  source (FILE)
     Parse and execute the contents of FILE.  This is equivalent to
     executing commands from a script file, but without requiring the
     file to be named `FILE.m'.
Galloway answered 13/7, 2013 at 1:14 Comment(1)
No, there is no source command in Matlab :(Cowell
W
3

You could also group functions in one main file together with the main function looking like this:

function [varargout] = main( subfun, varargin )
[varargout{1:nargout}] = feval( subfun, varargin{:} ); 

% paste your subfunctions below ....
function str=subfun1
str='hello'

Then calling subfun1 would look like this: str=main('subfun1')

Woorali answered 3/6, 2013 at 18:46 Comment(0)
C
0

As of R2017b, this is not officially possible. The relevant documentation states that:

Program files can contain multiple functions. If the file contains only function definitions, the first function is the main function, and is the function that MATLAB associates with the file name. Functions that follow the main function or script code are called local functions. Local functions are only available within the file.

However, workarounds suggested in other answers can achieve something similar.

Curcio answered 25/8, 2010 at 20:26 Comment(5)
This is not exactly what Gnovice stated at the beginning of his answer?Koah
@Koah Perhaps, but several years had passed since that answer, and somebody might wonder if anything changed.Curcio
I still didn't get if anything has changed...? :)Koah
Nope. Other than maybe some documentation that was added to address this specific topic.Curcio
The reason why I wrote this answer is because several releases ago they introduced functions you can add to the end of scripts - so one might wonder if anything changed in this regard as well (answer: no).Curcio
W
-2

I have try with the SCFRench and with the Ru Hasha on octave.

And finally it works: but I have done some modification

function message = makefuns
    assignin('base','fun1', @fun1);   % Ru Hasha
    assignin('base', 'fun2', @fun2);  % Ru Hasha
    message.fun1=@fun1;               % SCFrench
    message.fun2=@fun2;               % SCFrench
end

function y=fun1(x)
    y=x;
end

function z=fun2
    z=1;
end

Can be called in other 'm' file:

printf("%d\n", makefuns.fun1(123));
printf("%d\n", makefuns.fun2());

update:

I added an answer because neither the +72 nor the +20 worked in octave for me. The one I wrote works perfectly (and I tested it last Friday when I later wrote the post).

Wriggler answered 23/11, 2018 at 15:9 Comment(1)
If you can explain how this is different from the two existing answers that you are copying from, I'll remove my downvote. Sorry for not commenting earlier. I just don't see how this is different, except you combined both methods into one function and therefore are doing something redundant. Also, please insert proper links to the answers you are referencing, "+72" and "+20" is quite cryptic, it took me a while to realize you are referring to the vote counts, which will change over time and make your references unintelligible.Donaghue

© 2022 - 2024 — McMap. All rights reserved.