Skip to main content

matlab-validate-function-arguments

Use when writing MATLAB functions with arguments blocks — repeating arguments (arguments (Repeating)), .?ClassName property import in constructors, name-value forwarding with namedargs2cell, or migrating from inputParser or validateattributes. Also when reviewing signatures for implicit-conversion pitfalls (size reshaping, class coercion, computed defaults), or when restricting, constraining, or validating function inputs — scalar vs vector enforcement, type rejection, size checking. Also when asked to harden inputs, make a function more robust, tighten input checking, or rewrite for safer input acceptance — even without "validation" or "arguments block" wording. Triggers on: arguments block, mustBe validators, name-value arguments, varargin, inputParser, nargin/narginchk, restrict input, type checking, scalar constraint, harden inputs, defensive programming. Not for: App Designer callbacks, Simulink mask parameters, class inheritance, or runtime validation outside function or property declarations.

Source facts

Repository
matlab/matlab-agentic-toolkit
Last source activity
October 8, 2026 at 15:17
Detected SKILL.md language
English
Stars
1,278
Forks
148

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
6 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
matlab-validate-function-arguments
description
Use when writing MATLAB functions with arguments blocks — repeating arguments (arguments (Repeating)), .?ClassName property import in constructors, name-value forwarding with namedargs2cell, or migrating from inputParser or validateattributes. Also when reviewing signatures for implicit-conversion pitfalls (size reshaping, class coercion, computed defaults), or when restricting, constraining, or validating function inputs — scalar vs vector enforcement, type rejection, size checking. Also when asked to harden inputs, make a function more robust, tighten input checking, or rewrite for safer input acceptance — even without "validation" or "arguments block" wording. Triggers on: arguments block, mustBe validators, name-value arguments, varargin, inputParser, nargin/narginchk, restrict input, type checking, scalar constraint, harden inputs, defensive programming. Not for: App Designer callbacks, Simulink mask parameters, class inheritance, or runtime validation outside function or property declarations.
license
https://www.mathworks.com/content/dam/mathworks/license/pmrl/license.md
metadata
{"author":"MathWorks","version":"1.3"}
# MATLAB Function Argument Validation Write robust MATLAB functions using `arguments` blocks with correct semantics for size, class, repeating arguments, and property import. ## When to Use - Writing a function with an `arguments` block - Using repeating arguments (`arguments (Repeating)`) - Writing a class constructor that accepts name-value arguments - Migrating from `inputParser` or `validateattributes` - Reviewing a function signature for implicit conversion pitfalls - Choosing between class specs, `mustBeA`, and validators ## When NOT to Use - Basic MATLAB programming without argument validation - App building or UI components (use `matlab-build-app`) - Unit testing (use `matlab-write-tests`) - General OOP class design unrelated to argument validation - Simple `if`/`error` guard clauses for runtime invariants inside a function body (those aren't input validation — leave them as-is unless the user asks for an `arguments` block specifically) - **`.mlx` (Live Script) or `.mlapp` (App Designer) files** — these are binary ZIP containers. Don't unzip them or attempt structural edits. If the user asks to add an `arguments` block to a function inside one, ask them to export to plain `.m` first, or open the file in MATLAB and edit it there. ## Critical Misconceptions These are things the agent commonly gets wrong. Read these FIRST. ### Size specs RESHAPE, not reject **WRONG belief:** `(1,:)` rejects column vectors with an error. **ACTUAL behavior:** MATLAB silently reshapes the input to fit the declared size. ```matlab function out = myFunc(x) arguments x (1,:) double end out = x; end myFunc([1; 2; 3]) % Does NOT error! Returns [1 2 3] (reshaped to row) ``` A column vector `[1;2;3]` passed to `(1,:)` becomes a row vector `[1 2 3]`. To actually reject column vectors, use a validator: ```matlab function out = myFunc(x) arguments x {mustBeNumeric, mustBeRow} end out = x; end ``` ### Class specs CONVERT, not reject **WRONG belief:** `double` in the arguments block rejects non-double inputs. **ACTUAL behavior:** MATLAB attempts implicit conversion to the declared class. ```matlab function out = myFunc(x) arguments x double end out = x; end myFunc('hello') % Does NOT error! Returns [104 101 108 108 111] (ASCII codes) myFunc(single(3.14)) % Does NOT error! Returns double(3.14) ``` To reject without converting, use `mustBeA` or `mustBeFloat`: ```matlab x {mustBeA(x, "double")} % Rejects single, char, int32, etc. x {mustBeFloat} % Accepts single OR double, rejects char/int x {mustBeNumeric} % Accepts any numeric, rejects char/string ``` ### Numeric validators don't reject complex values **WRONG belief:** `mustBeNumeric`, `mustBeFinite`, and `mustBeInteger` reject complex inputs like `1+2i`. **ACTUAL behavior:** Complex values are numeric, finite, and (when their real and imaginary parts are integer-valued) integer — so `1+2i` passes all three silently. Sizes, indices, counts, and most physical scalars should reject complex values explicitly: ```matlab function H = hilb2(n) arguments n (1,1) {mustBeInteger, mustBePositive, mustBeReal} end H = 1./((1:n)' + (0:n-1)); end ``` Add `mustBeReal` whenever a complex input would be nonsensical for the function's contract. ### Computed defaults see PASSED values, not declared defaults **WRONG belief:** Default expressions use the declared default values of earlier arguments. **ACTUAL behavior:** Default expressions evaluate using the actual passed values. ```matlab function out = myFunc(fs, windowSize) arguments fs (1,1) double {mustBePositive} windowSize (1,1) double {mustBePositive} = round(fs / 10) end out = windowSize; end myFunc(8000) % windowSize = round(8000/10) = 800 (uses passed fs) myFunc(8000, 256) % windowSize = 256 (explicitly passed) ``` This eliminates the need for sentinel values (`[]`) and post-validation fixup. ### `~` is a valid placeholder — don't rename it **WRONG belief:** A name in the `arguments` block is mandatory, so a `~` placeholder in the function signature must be renamed to `obj`/`this`/etc. **ACTUAL behavior:** `~` is valid as an argument-block name (R2019b+). Keep it. ```matlab function normalize(~, results) arguments ~ results (1,:) struct end ... end ``` When a method signature uses `~` to mark an unused input (e.g. an unused class instance), **preserve the `~`** in the arguments block: - **No class or size spec on `~`** — type specs like `(1,1) MetricCalculator` require a name, so adding one forces a rename. Skip the spec entirely. - **No `%#ok<INUSL>` / `%#ok<INUSA>` / `%#ok<MANU>` pragma** — `~` already tells the lint pass the input is intentionally unused. - **Don't rename `~` to `obj`** to "tighten validation." Renaming reintroduces the lint warning the original `~` was suppressing, with no contract benefit. ## Patterns ### Repeating Arguments Use `arguments (Repeating)` for functions accepting variable groups of arguments (like `plot(x1,y1,x2,y2,...)`). Each declared variable becomes a **cell array** in the function body. ```matlab function plotMultiSeries(x, y) arguments (Repeating) x (1,:) double {mustBeFinite} y (1,:) double {mustBeFinite} end figure; hold on; for i = 1:numel(x) plot(x{i}, y{i}); end hold off; end ``` Key rules: - Variables become cell arrays — access with `x{i}`, not `x(i)` - All variables in the group repeat together (complete sets) - Repeating arguments cannot have default values - Zero repetitions is valid (produces empty cell arrays) ### Output Argument Validation — `arguments (Output)` and `(Output, Repeating)` > **R2022b+.** Output argument validation is unavailable in earlier releases — > input validation (the bulk of this skill) works from R2019b onward. Use `arguments (Output, Repeating)` to declare a function whose output count scales with `nargout`. The block must declare **exactly one** name — MATLAB rejects multi-name repeating output blocks with `MATLAB:functionValidation:MultipleRepeatingOutputs`. To return groups of related values (e.g. triples), pack them into the single output and have the caller request `N * groupSize` outputs. ```matlab function out = productTriples() arguments (Output, Repeating) out (1,1) double end out = cell(1, nargout); for k = 1:3:nargout b = rand; c = rand; out{k} = b * c; out{k+1} = b; out{k+2} = c; end end ``` Caller: `[p1, a1, b1, p2, a2, b2] = productTriples();` Key rules: - **One name only** — `arguments (Output, Repeating) a; b; c; end` errors at parse - The output is assigned a `1×nargout` cell array; comma-list expansion at the call site distributes its contents across the requested LHS variables - Validators on the single declared name apply to **each cell element** - `nargout` tells the body how many outputs were requested; zero is valid ### Composition Rules — What Can Coexist A function may have **multiple `arguments` blocks**. The rules below apply to the function as a whole — argument categories must appear in this order across all blocks combined: ``` required → optional (with defaults) → repeating → name-value ``` Violating the order at any point — even across separate blocks — fails to parse. Don't trust intuition: **all of these compose legally in one function**: - required + optional + repeating + name-value (`.?ClassName` allowed too) - required + repeating + name-value - repeating + name-value - `(Output, Repeating)` plus any combination of input blocks - `~` placeholders inside a `(Repeating)` block **Multiplicity:** | Block kind | How many allowed | |------------|------------------| | Plain `arguments` (positional and/or name-value) | Multiple, in order | | `arguments (Repeating)` (input) | **Exactly one** per function | | `arguments (Output, Repeating)` | **Exactly one** per function | | Name-value structs across plain blocks | Multiple — different struct names | **Parse-time error identifiers** — when in doubt, write the function and let MATLAB tell you. These are the only errors composition can produce; the names spell out the rule: | Identifier | Means | |------------|-------| | `MATLAB:functionValidation:RequiredAfterOptional` | A required arg appears after one with a default | | `MATLAB:functionValidation:OptionalAfterRepeating` | An optional/positional arg appears after the repeating block | | `MATLAB:functionValidation:PositionalAfterNamed` | A positional or repeating arg appears after a name-value arg | | `MATLAB:functionValidation:MultipleRepeatingBlocks` | More than one `(Repeating)` block (input or output) | | `MATLAB:functionValidation:RepeatingHasDefault` | A `(Repeating)` arg has a default value | If you're unsure whether a combination is legal, **don't fabricate a restriction** — write a minimal version and run it. The error identifier (or its absence) is the answer. #### Maximal example A single function with required + optional + ignored + repeating + ignored repeating + name-value + class-imported name-value (here `SensorConfig` — the class defined in the `.?ClassName` section above): ```matlab function maximal(req, opt, ~, x, ~, options, classArg) arguments req (1,1) double opt (1,1) double = 7 ~ end arguments (Repeating) x (1,1) double ~ end arguments options.Title (1,1) string = "default" options.Verbose (1,1) logical = false classArg.?SensorConfig end % function body end ``` Call: `maximal(1, 2, 3, 4, 'a', 5, 'b', Title="t", SampleRate=44100)` — parses and runs. `SampleRate` is one of the name-value args imported from `SensorConfig` by the `.?` line. **Don't pick a class with no public-settable properties** for `.?ClassName` — `onCleanup`, for example, has only `task` (private set), so `.?onCleanup` imports zero name-value args. The line is syntactically valid but a no-op, and any "name-value" the caller writes against it is treated as an unknown name — see "unknown `Name=Value` is silently swallowed" in Common Mistakes. For combining repeating args with name-value options, see the Maximal example above and [references/examples/repeating-args.md](references/examples/repeating-args.md). ### .?ClassName — Import Properties as Name-Value Args Use `.?ClassName` in constructors to derive name-value arguments directly from property definitions. This avoids redeclaring properties in the arguments block. For additional patterns — overriding specific properties, static factory with forwarding, and wrapping graphics-class properties — see [references/examples/dot-question-syntax.md](references/examples/dot-question-syntax.md). ```matlab classdef SensorConfig properties SampleRate (1,1) double {mustBePositive} = 1000 Resolution (1,1) double {mustBePositive, mustBeInteger} = 16 FilterOrder (1,1) double {mustBePositive, mustBeInteger} = 4 Label (1,1) string = "unnamed" end methods function obj = SensorConfig(nvArgs) arguments nvArgs.?SensorConfig end props = fieldnames(nvArgs); for i = 1:numel(props) obj.(props{i}) = nvArgs.(props{i}); end end end end ``` Benefits: - No duplication of size, class, validators, or defaults - Constructor stays in sync when properties are added or removed - Tab completion shows all settable properties automatically ### namedargs2cell — Forward Name-Value Args Use `namedargs2cell` to convert a validated struct back to a name-value cell array for forwarding to other functions: ```matlab function obj = fromPreset(presetName, nvArgs) arguments presetName (1,1) string nvArgs.?SensorConfig end switch presetName case "audio" defaults = struct(SampleRate=44100, Resolution=24, Label="audio"); case "vibration" defaults = struct(SampleRate=10000, Resolution=16, Label="vibration"); end % Apply overrides overrides = fieldnames(nvArgs); for i = 1:numel(overrides) defaults.(overrides{i}) = nvArgs.(overrides{i}); end args = namedargs2cell(defaults); obj = SensorConfig(args{:}); end ``` ## Migration Decision Framework When migrating from `inputParser` or `validateattributes`, use this decision tree for class handling: | Original check | What it does | Arguments block equivalent | Why | |---------------|-------------|---------------------------|-----| | `@isnumeric` | Accepts any numeric, no conversion | `{mustBeNumeric}` | No class spec — avoids conversion | | `@ischar` | Accepts char only | `{mustBeA(label, 'char')}` or `(1,:) char` | `mustBeText`/`mustBeTextScalar` widens to accept string | | `@islogical` | Accepts logical only | `(1,1) {mustBeA(x, 'logical')}` | A `logical` class spec CONVERTS — `logical(1)` → `true`, so `1`/`0` (and other convertible scalars) would be accepted where `@islogical` rejects them. Use `mustBeA` (no class spec) to reject without converting. | | `{'numeric'}` | Accepts any numeric, no conversion | `{mustBeNumeric}` | `validateattributes` meta-class — same set as `@isnumeric` | | `{'float'}` | Accepts single or double | `{mustBeFloat}` | Equivalent to `{'single','double'}` | | `{'integer'}` (class spec, rare) | Accepts only integer types (int8…uint64) | Usually `{mustBeNumeric, mustBeInteger}`. Strict-only-if-intentional: `{mustBeA(x, ["int8","int16","int32","int64","uint8","uint16","uint32","uint64"])}` | The class-only form rejects integer-valued doubles like `5.0` — usually accidental. Widen to the lenient pairing unless the original code clearly meant to reject doubles. | | `{'numeric'}, {'integer'}` (class+attr) | Numeric, integer-valued | `{mustBeNumeric, mustBeInteger}` | Common pairing — accepts both int types and integer-valued floats |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub