Table of Contents
Why Organize Code into Multiple Functions
As your MATLAB programs grow, placing all code into a single long file quickly becomes hard to read, debug, and reuse. Splitting code into multiple functions lets you separate tasks into smaller, well defined pieces. Each function can focus on one job, can be tested on its own, and can be reused in other projects.
In this chapter the focus is on how to structure MATLAB code across several functions and files, how they see each other, and how to keep things organized at the project level. Details about how to create a single function, define inputs and outputs, or use the path are covered in other chapters, so they are not repeated here.
One Main Script or Function, Many Helper Functions
A common organization pattern is to have one main entry point and several helper functions that perform subtasks.
The main script or main function usually:
- Reads input data or sets parameters.
- Calls helper functions to perform computations.
- Produces output, such as plots, files, or numeric results.
For example, a main function might look like this:
function mainAnalysis()
data = load("measurements.mat");
cleaned = cleanData(data.raw);
stats = computeStatistics(cleaned);
showResults(stats);
end
Here, mainAnalysis is the single point you run. It delegates specific tasks to cleanData, computeStatistics, and showResults. Each helper has a clear purpose and can be stored either in its own file or as a local function in the same file, depending on how you want to organize your project.
When you think about organization, it helps to ask: “Does this code perform a single, clear task?” If not, consider splitting it into smaller functions.
Organizing One File with Multiple Local Functions
In MATLAB, a single .m file can contain a main function followed by additional functions. These additional functions are called local functions. They are visible only inside that file and cannot be called directly from other files.
A typical structure is:
function mainFunction()
% code of the main function
result = helperA(10);
helperB(result);
end
function out = helperA(x)
out = x.^2;
end
function helperB(y)
disp(y);
endIn this file:
mainFunction must appear first.
helperA and helperB are local functions and can be called from mainFunction and from each other inside the file.
Other files cannot call helperA or helperB by name. They are private to this file.
If the first code block in the file is a function definition, MATLAB treats the file as a function file. In that case, you cannot mix top level script code before the first function. Everything at the top must belong to the first function.
Local functions are useful when you want to keep related helper code close to the main function but do not want to expose these helpers as general tools for the rest of your project.
One Function per File and File Names
Another common approach is to place each reusable function in its own .m file. In this pattern, each file defines one primary function whose name must match the file name exactly.
For example, a file named smoothSignal.m might contain:
function y = smoothSignal(x, windowSize)
y = movmean(x, windowSize);
end
Here, the function name smoothSignal is the same as the file name smoothSignal.m. This function can now be called from any script or function in your project, as long as MATLAB can find the file through the path.
You can still define local functions below the main function in a function file that has one primary public function. Those local functions remain private to that file, while the main function is visible to other files.
Using one public function per file is helpful when you want to build a library of utilities. Each utility function has its own file, clear name, and its own help section.
Choosing Between Local Functions and Separate Files
Both local functions and one function per file are useful. The choice depends on how you want to use the code.
Use local functions in the same file when:
The helper is only meaningful in the context of a single main function.
You want to keep related code grouped together in one file.
You do not intend to call the helper from other files.
Use separate function files when:
You want to reuse the function across different scripts or projects.
You want the function to appear in the Function Browser and be easy to find.
You want a clear, single responsibility per file.
Sometimes a helper starts out as a local function. If you later find yourself wanting to use it from other files, move it into its own .m file and give that file the same name as the function.
Structuring Projects with Folders
As your collection of function files grows, it becomes important to group them into folders. A simple project might have a structure like:
projectRoot/
mainAnalysis.m
+preprocess/
cleanData.m
normalizeValues.m
+stats/
computeStatistics.m
+plotting/
showResults.mHere, functions are grouped by their purpose. This makes it easier to navigate the project and understand which area of the codebase handles which tasks.
You can also keep experiments or temporary code in a separate folder from your core functions. For instance, have a sandbox folder for trying ideas and a src folder for the main code. The exact structure is flexible, but consistency is important. Once you decide on a structure, follow it throughout the project so that future you can understand what you did.
Using Subfolders and Packages
MATLAB supports packages, which are folders whose names start with a plus sign. Packages help you group functions under a common namespace. For example, you can create a folder called +imageTools and a function file inside it called filterEdges.m:
+imageTools/
filterEdges.mThe function file:
function out = filterEdges(in)
% some processing
out = in; % placeholder
endTo call this function from outside the package, you use the package name:
result = imageTools.filterEdges(data);
The package name imageTools helps avoid name conflicts and clarifies where the function comes from. If you have another package +audioTools with a function filterEdges.m, then you can call audioTools.filterEdges or imageTools.filterEdges explicitly.
Packages are especially useful in larger projects or when you create your own toolbox-like collections. They give structure and also avoid accidental reuse of the same function name for different purposes.
Private Functions Using private Folders
Sometimes you want functions that are shared by several files in the same folder, but that should not be visible to the rest of the project. MATLAB supports this with a special folder named private.
You can create a folder structure like:
projectRoot/
mainAnalysis.m
helperFunction.m
private/
internalCompute.m
Any function inside private can be called only by functions that reside in the folder above private. Files in other folders, even if they are on the path, cannot call internalCompute.
For example, helperFunction.m could contain:
function y = helperFunction(x)
y = internalCompute(x);
end
And internalCompute.m in the private folder:
function out = internalCompute(in)
out = in.^2;
end
This setup helps you organize internal implementation details separately from the main interface of your project. It also communicates intent: functions in private are not part of the public interface and may change without notice.
Shared Helpers vs Project Specific Helpers
In a larger codebase, you might have two levels of helper functions:
General purpose helpers that are useful across many projects, for example normalizeVector, safeDivide, or plotNiceGrid.
Project specific helpers that only make sense inside a particular project, for example readExperimentConfig or convertSensorUnits.
General purpose helpers are good candidates for a separate folder that you can add to the MATLAB path. Within that folder you might organize further with packages.
Project specific helpers can live inside the project folder, possibly arranged into subfolders or packages by topic. Private folders can hide truly internal details so that other projects do not accidentally rely on them.
Thinking about which functions are “public” for the project and which are internal helps you decide where to place them and how to name them.
Layering Functions and Avoiding Deep Chains
When you split code into many functions it is possible to create very deep chains, where each function calls another, and so on. If you are not careful this can make the flow hard to follow.
A practical guideline is to design layers:
Top layer functions coordinate the overall task and call mid layer functions.
Mid layer functions perform logically complete subtasks and call low layer utilities.
Low layer utilities perform very small, shared operations and do not know about the larger task.
For example:
runPipeline calls loadData, preprocessData, analyzeData, generateReport.
preprocessData may call cleanMissing, smoothSignals.
smoothSignals may call a low level utility like applyMovingAverage.
This layered approach makes it clear which functions depend on which others. Avoid long chains where each function does an almost trivial handoff to the next. When a function exists only to call another function once, consider whether you can merge them or give each a clearer responsibility.
Organizing Help, Comments, and Function Interfaces
When you work with multiple functions, consistency in documentation and interfaces becomes important. Each public function should begin with a help section that clearly explains what it does, its inputs, and its outputs.
For example:
function y = normalizeVector(x)
% NORMALIZEVECTOR Scale a vector to unit length.
% Y = NORMALIZEVECTOR(X) returns Y such that
% norm(Y) = 1, if X is not the zero vector.
n = norm(x);
if n == 0
y = x;
else
y = x ./ n;
end
endUse similar style for related functions so that users know what to expect. Internal or local functions might have shorter comments but still benefit from a brief description.
Interfaces should be stable for public functions. If you change the inputs or outputs of a commonly used function, it may break many callers. Internal functions can be more flexible to change, but it is still helpful to keep their interfaces clear.
Calling Functions Across Files
When your code is split into multiple functions and files, MATLAB determines which function to call based on the function name, the current folder, and the search path.
If two different files define functions with the same name, MATLAB uses a defined order to decide which one it calls, often preferring functions in the current folder. In a well organized project, you usually avoid such name conflicts by:
Using descriptive names that reflect the purpose of the function, such as loadPatientData instead of plain loadData.
Using packages, for example exp1.loadData and exp2.loadData, if you have separate experiments.
Keeping local or private functions hidden from the rest of the project when they are not meant to be reused.
When you introduce a new function file, make sure that its name matches the function name and that the file is located in a folder that MATLAB can access through the path.
Testing and Reusing Functions
A benefit of organizing code into multiple functions is that each function becomes easier to test. To test a function, you can write a small script or live script that calls it with different inputs and checks whether the outputs make sense.
For example:
x = [1 2 3];
y = normalizeVector(x);
disp(norm(y))
This directly tests normalizeVector without involving the rest of the project. As you accumulate such tests, you gain confidence that changes to one function do not silently break others.
When you notice that the same helper is useful across multiple projects, consider moving it to a shared folder of utilities. That folder can be added to the path from each project, so you avoid copying and pasting code between projects.
Evolving Structure Over Time
At the start of a project you may not know the best way to organize your functions. It is normal to begin with a small number of files and then refactor as the project grows.
Common changes include:
Splitting a large function into a main function and several local helpers.
Promoting a local function to its own .m file when you want to reuse it.
Moving related functions into a dedicated subfolder or package.
Creating a private folder to hide internal details.
Because MATLAB relies on file names and folder structure, be deliberate when you rename or move functions. After changes, run your main script or test scripts to check that everything still works.
Important points to remember:
Each .m file can define a main function and optional local functions. Local functions are only visible within that file.
Public functions must have the same name as their .m file and can be called from other files on the path.
Use separate files for reusable utilities, and use local or private functions for helpers that are internal to a file or folder.
Organize related functions into folders and, for larger projects, consider packages using +packageName folders to avoid name conflicts.
Let your structure evolve. Start simple, then refactor into multiple functions and folders as your codebase grows.