関数の引数の検証
関数の引数の検証は、関数の引数に特定の制限を宣言するための 1 つの方法です。引数の検証を使用すると、引数のクラス、サイズ、および他の特性を制約することができ、これらのテストを実行するコードを関数本体に記述する必要はありません。
関数の引数の検証は宣言型であるため、MATLAB® デスクトップ ツールで特定のコード ブロックを調べて関数に関する情報を抽出できます。引数の要件を宣言することにより、煩雑な引数チェックのコードをなくし、コードの可読性、ロバスト性、および保守性を向上させることができます。
関数の引数の検証構文により、オプション引数、繰り返し引数、および名前と値の引数を定義するプロセスが簡略化されます。また、この構文を使用すると、一貫した方法で既定値を定義できるようになります。
引数の検証を使用する場所
関数の引数の検証は、関数定義でオプションとして使用します。引数の検証が最も役に立つのは、任意のコードで呼び出され、関数コードを実行する前に引数の有効性を判定しなければならない関数内です。作成者以外が使用するために設計されている関数では、引数を適度に制限したり、その引数の検証チェックに基づいて特定のエラー メッセージを返したりできるというメリットがあります。
検証が必要でない場所
ローカル関数とプライベート関数、およびプライベート メソッドや保護されたメソッドでは、呼び出し元で入力の要件が認識されるため、これらのタイプの関数は有効な引数を指定して呼び出すことができます。
検証が許可されていない場所
引数の検証構文は、入れ子関数、抽象メソッド、またはハンドル クラスのデストラクター メソッドでは使用できません。メソッド内での引数の検証の詳細については、メソッドの構文を参照してください。
arguments
ブロック構文
関数は、キーワード arguments
および end
で区切られたオプションのコード ブロック内で、引数の検証を定義します。使用した場合、arguments
ブロックは関数の最初の実行可能行より前に開始されなければなりません。
関数内で複数の arguments
ブロックを使用できますが、すべてのブロックは、arguments
ブロックの一部ではないコードより前になければなりません。
以下のコードの強調表示されている部分は、入力引数検証の構文を示しています。
関数の引数の宣言には、以下の種類の制限をどれでも含めることができます。
サイズ — 各次元の長さ。小かっこで囲みます。
クラス — 単一の MATLAB クラスの名前。
関数 — 検証関数のコンマ区切りリスト。中かっこで囲みます。
入力引数の既定値を、その引数についての関数の検証宣言内で定義することもできます。既定値は、その引数に対して宣言された制限を満たさなければなりません。
サイズおよびクラスの検証
サイズ
検証サイズは引数の次元であり、非負の整数値またはコロン (:
) で指定します。コロンは、その次元で任意の長さが許可されることを示します。次元には式を使用できません。関数呼び出しで引数に代入される値は、指定されたサイズと適合していなければならず、そうでない場合、MATLAB はエラーをスローします。
サイズの指定には、MATLAB のインデックス付き代入の規則が適用されます。たとえば、1 行 1 列の値は (5,3)
として指定されたサイズと適合しますが、これは、MATLAB でスカラー拡張が適用されるためです。また、MATLAB の行と列の変換が適用され、(1,:)
と指定されたサイズは 1 行 n 列および n 行 1 列のサイズを受け入れることができます。
以下にいくつかの例を示します。
(1,1)
— 入力は厳密に 1 行 1 列でなければならない。(3,:)
— 最初の次元は 3 でなければならず、2 番目の次元は任意の値にできる。
サイズを指定しない場合、検証関数で制限されていない限り、任意のサイズが許可される。
クラス
検証クラスは単一のクラスの名前です。関数の入力に代入される値は、指定されたクラスであるか、指定されたクラスに変換可能でなければなりません。Java クラスと COM クラス、および classdef
キーワードを使用しない MATLAB クラス定義 (MATLAB ソフトウェア Version 7.6 より前に定義されたクラス) を除く、任意の MATLAB クラス、または MATLAB でサポートされている外部定義クラスを使用してください。
以下にいくつかの例を示します。
char
— 入力はchar
クラスか、またはstring
のように MATLAB でchar
に変換可能な値でなければならない。double
— 任意の精度の数値が入力可能。cell
— 入力は cell 配列でなければならない。ユーザー定義クラス
クラスを指定しない場合、検証関数で制限されていない限り、任意のクラスが許可される。
例: 基本の引数の検証
次の arguments
ブロックは、3 つの入力のサイズとクラスを指定します。
function out = myFunction(A, B, C) arguments A (1,1) string B (1,:) double C (2,2) cell end % Function code ... end
この関数では、変数は以下の検証要件を満たさなければなりません。
A
は string スカラー。B
は 1 行で任意の長さ列の double のベクトル。C
は 2 行 2 列の cell 配列。
検証関数
検証関数は、引数値が特定の要件を満たさない場合にエラーをスローする MATLAB 関数です。検証関数は値を返さず、クラスやサイズとは異なり、検証対象の引数の値を変更できません。
検証プロセス中、MATLAB は引数用にリストされている各検証関数にその引数の値を渡します。検証関数に渡される値は、クラスとサイズの指定によって行われた変換の結果です。MATLAB は各関数を左から右の順序で呼び出し、最初に見つかったエラーをスローします。
事前定義された検証関数の表は、引数の検証関数を参照してください。
例: 検証関数を使用した特定の制限の設定
検証関数は、より具体的な方法で引数を制限できます。事前定義された検証関数を多くの一般的な種類の検証に使用したり、特定の要件を満たす独自の検証関数を定義することができます。
たとえば、以下の関数は mustBeNumeric
、mustBeReal
、mustBeMember
、およびローカル関数 mustBeEqualSize
を使用して、次の検証を指定します。
入力
x
は任意の長さの実数値行ベクトルでなければならない。入力
v
はx
と同じサイズの実数値行ベクトルでなければならない。入力
method
は、許可された 3 つの選択肢のいずれかにあたる文字ベクトルでなければならない。method
は既定値を指定しているため、この引数は任意です。
function myInterp(x,v,method) arguments x (1,:) {mustBeNumeric,mustBeReal} v (1,:) {mustBeNumeric,mustBeReal,mustBeEqualSize(v,x)} method (1,:) char {mustBeMember(method,{'linear','cubic','spline'})} = 'linear' end % Function code .... end % Custom validation function function mustBeEqualSize(a,b) % Test for equal size if ~isequal(size(a),size(b)) eid = 'Size:notEqual'; msg = 'Size of first input must equal size of second input.'; error(eid,msg) end end
関数の引数の検証は、カスタムの検証関数内では使用しないでください。検証関数の定義の詳細、および事前定義された検証関数のリストについては、引数の検証関数を参照してください。
既定値
入力引数の既定値には、サイズ、クラス、および検証関数の各要件を満たす任意の定数または式を使用できます。引数の宣言で既定値を指定すると、その引数は任意になります。MATLAB は、関数呼び出しに引数が含まれていない場合、その既定値を使用します。既定値の式は、既定値が使用されるたびに評価されます。
メモ
MATLAB は、引数の値を指定せずに関数が呼び出された場合にのみ既定値を検証するため、無効な既定値は、その引数を指定せずに関数が呼び出された場合にのみエラーになります。
オプションの引数は、関数シグネチャと arguments
ブロック内で必須の引数の後に配置しなければなりません。オプションの引数の詳細については、必須の位置引数とオプションの位置引数の検証を参照してください。
宣言されたクラスおよびサイズへの変換
クラス検証とサイズ検証はどちらも引数の値を変更できます。MATLAB で実行可能な変換の例をここにいくつか挙げます。
クラスの制限を満たす場合は次のとおりです。
char
値をstring
値に変換可能。single
値をdouble
に変換可能。
サイズの制限を満たす場合は次のとおりです。
スカラー拡張は入力サイズをスカラーから非スカラーに変更可能。
列ベクトルを行ベクトルに変換可能。
結果として、関数本体で検証された値が、関数の呼び出し時に渡された値と異なる場合があります。クラスの変換の詳細については、暗黙的なクラス変換を参照してください。検証時のクラスとサイズの変換を避けるには、代わりに引数の検証関数を使用します。詳細については、Use Validation Functions to Avoid Unwanted Class and Size Conversionsを参照してください。
例: 値の変換
以下の関数は、arguments
ブロックで指定されたクラスと一致させるために、入力を変換する方法を示しています。SpeedEnum
クラスは、3 番目の引数が取り得る値を定義するために作成された列挙クラスです。
function forwardSpeed(a,b,c) arguments a double b char c SpeedEnum end % Function code disp(class(a)) disp(class(b)) disp(class(c)) end
列挙型クラスは次のようになります。
classdef SpeedEnum < int32 enumeration Full (100) Half (50) Stop (0) end end
関数に対するこの呼び出しでは、宣言された型に MATLAB が変換できる入力値が使用されます。関数内の実際の引数の型が出力として表示されます。
forwardSpeed(int8(4),"A string",'full')
double char SpeedEnum
出力引数の検証
R2022b 以降、引数の検証を出力引数で使用できます。入力引数と同様に、出力引数のクラスとサイズを検証できます。また、検証関数を適用することもできます。ただし、出力引数の既定値を指定したり、以前に宣言した引数を参照したりすることはできません。出力引数の検証は常に任意です。出力引数の検証を追加すると、コードが読みやすくなります。また、いずれ変更される可能性のあるコードの一貫した出力も維持されます。
入力引数と出力引数を検証するには、個別の arguments
ブロックを使用する必要があります。arguments
ステートメントの後に arguments ブロックのタイプ (Input)
または (Output)
を定義します。(Input)
と (Output)
の両方の引数ブロックを使用する場合、(Output)
ブロックは (Input)
ブロックの後に続ける必要があります。タイプを指定しない場合、MATLAB はブロックに入力引数が含まれていると仮定します。
詳細については、arguments
を参照してください。
例: 出力引数の検証
R2022b 以降、引数の検証を出力引数で使用できます。
たとえば、次の関数は、3 つの入力引数と 1 つの出力引数のサイズとクラスを、個別の arguments ブロックを使用して検証します。(Input)
ブロックは、(Output)
ブロックの前に配置する必要があります。
function out = myFunction(A, B, C) arguments (Input) A (1,1) string B (1,:) double C (2,2) cell end arguments (Output) out (1,:) double end % Function code ... end
引数の種類
関数の引数の検証では、4 種類の引数を宣言できます。関数は、これらの種類の引数をどれでも定義できますが、引数は以下の順序で定義しなければなりません。
引数タイプ | 追加情報 |
---|---|
1. 必須の位置引数 | 必須の位置引数とオプションの位置引数の検証 |
2. オプションの位置引数 | |
3. 繰り返しの位置引数 | 繰り返し引数の検証 |
4. オプションの名前と値の引数 | 名前と値の引数の検証 |
引数の検証の順序
関数が呼び出されると、MATLAB は引数をそれらが arguments
ブロックで宣言されている順序、つまり上から下への順序で検証します。各引数は、次の引数が検証される前に完全に検証されます。したがって、前に宣言された引数へのすべての参照では、検証済みの値が使用されます。最初の検証が失敗すると、関数はエラーをスローします。
検証された値は、関数の呼び出しに際して入力として渡された元の値と異なる場合があります。たとえば、次の関数はクラス uint32
の値として入力を宣言します。3 番目の入力の宣言は、最初の 2 つの入力の積に等しい既定値を代入します。
function c = f(a, b,c) arguments a uint32 b uint32 c uint32 = a.* b end % Function code ... end
異なる数値クラス (double
など) の入力を指定して関数を呼び出すと、uint32
に変換される結果となります。
c = f(1.8,1.5)
関数呼び出しでオプションの引数 c
が指定されていないため、MATLAB は、a
および b
を uint32
値に変換した後、既定値を評価して c
に代入します。この場合、変換の結果、どちらの入力の値も 2 になります。したがって、a
と b
の積は 4 になります。
c = uint32 4
3 番目の入力に値を指定する場合、関数は値を c
に代入し、既定値の式は評価しません。
c = f(1.8,1.5,25)
c = uint32 25
変数および関数へのアクセスの制限
arguments
ブロックは関数のワークスペース内にあります。import
コマンドを使用して関数のスコープに追加されたパッケージ、クラスまたは関数はすべて、arguments
ブロックのスコープに追加されます。
検証関数と既定値の式から参照できる変数は、既に宣言されている入力変数のみです。次の関数では、c
の既定値は a
と b
から派生します。
function c = f(a,b,c) arguments a uint32 b uint32 c uint32 = a * b end % Function code ... end
しかし、arguments
ブロックでまだ宣言されていない入力変数は、参照できません。たとえば、前の関数で次の宣言を引数 a
に使用することは有効ではありません。これは、b
と c
がまだ宣言されていないためです。
arguments a uint32 = b * c b uint32 c uint32 end
引数の検証の式は、先に宣言された引数、つまり検証済みの引数のみを参照できます。検証関数と、名前と値の引数の既定値は、他の名前と値の引数にアクセスできません。
arguments
ブロック内の関数の制限
先に宣言された変数への参照はすべて、検証関数と既定値のテキスト内で可視でなければなりません。コードの透明性を確保するため、関数ワークスペースとやり取りする関数は使用しないでください。具体的には、入れ子関数や次の表にリストされている関数を arguments
ブロックで使用しないでください。
assignin | builtin | clear |
dbstack | eval | evalc |
evalin | exist | feval |
input | inputname | load |
nargin | narginchk | nargoutchk |
save | whos | who |
これらの制限は、arguments
ブロック内でのみ適用され、関数本体の変数や関数には適用されません。
arguments ブロックのデバッグ
arguments ブロック内でデバッグしている間、ワークスペースは "読み取り専用" になります。つまり、ワークスペースを確認したり、変数に割り当てられた値を表示したりすることはできます。ただし、ワークスペースが読み取り専用の間に、新しい変数を作成したり、既存の変数に割り当てられた値を変更したりすることはできません。デバッガーが arguments ブロックの範囲外になると、再び変数の作成または編集が可能になります。