Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

関数の引数の検証

引数の検証の紹介

関数の引数の検証は、関数の引数に特定の制限を宣言するための 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 配列でなければならない。

  • ユーザー定義クラス

クラスを指定しない場合、検証関数で制限されていない限り、任意のクラスが許可される。

検証関数

検証関数は、引数値が特定の要件を満たさない場合にエラーをスローする MATLAB 関数です。検証関数は値を返さず、クラスやサイズとは異なり、検証対象の引数の値を変更できません。

検証プロセス中、MATLAB は引数用にリストされている各検証関数にその引数の値を渡します。検証関数に渡される値は、クラスとサイズの指定によって行われた変換の結果です。MATLAB は各関数を左から右の順序で呼び出し、最初に見つかったエラーをスローします。

事前定義された検証関数の表は、引数の検証関数を参照してください。

既定値

入力引数の既定値には、サイズ、クラス、および検証関数の各要件を満たす任意の定数または式を使用できます。引数の宣言で既定値を指定すると、その引数は任意になります。MATLAB は、関数呼び出しに引数が含まれていない場合、その既定値を使用します。既定値の式は、既定値が使用されるたびに評価されます。

メモ

MATLAB は、引数の値を指定せずに関数が呼び出された場合にのみ既定値を検証するため、無効な既定値は、その引数を指定せずに関数が呼び出された場合にのみエラーになります。

オプションの引数は、関数シグネチャと arguments ブロック内で必須の引数の後に配置しなければなりません。オプションの引数の詳細については、必須の位置引数とオプションの位置引数を参照してください。

検証シーケンス

引数は、arguments ブロックで上から下へと検証されます。MATLAB は引数宣言の各部分を特定の順序で検証します。最初にクラスが、次にサイズが検証されます。クラスとサイズの検証結果が検証関数に渡されます。クラス、サイズ、検証関数が引数宣言にあるかどうかによって、各ステップは任意になります。

詳細については、引数の検証の順序を参照してください。

宣言されたクラスおよびサイズへの変換

クラス検証とサイズ検証はどちらも引数の値を変更できます。MATLAB で実行可能な変換の例をここにいくつか挙げます。

クラスの制限を満たす場合は次のとおりです。

  • char 値を string 値に変換可能。

  • single 値を double に変換可能。

サイズの制限を満たす場合は次のとおりです。

  • スカラー拡張は入力サイズをスカラーから非スカラーに変更可能。

  • 列ベクトルを行ベクトルに変換可能。

結果として、関数本体で検証された値が、関数の呼び出し時に渡された値と異なる場合があります。クラスの変換の詳細については、暗黙的なクラス変換を参照してください。検証時のクラスとサイズの変換を避けるには、代わりに引数の検証関数を使用します。詳細については、クラスとサイズの変換の回避を参照してください。

出力引数の検証

R2022b 以降、引数の検証を出力引数で使用できます。入力引数と同様に、出力引数のクラスとサイズを検証できます。また、検証関数を適用することもできます。ただし、出力引数の既定値を指定したり、以前に宣言した引数を参照したりすることはできません。出力引数の検証は常に任意です。出力引数の検証を追加すると、コードが読みやすくなります。また、いずれ変更される可能性のあるコードの一貫した出力も維持されます。

入力引数と出力引数を検証するには、個別の arguments ブロックを使用する必要があります。arguments ステートメントの後に引数ブロックのタイプ (Input) または (Output) を定義します。(Input)(Output) の両方の引数ブロックを使用する場合、(Output) ブロックは (Input) ブロックの後に続ける必要があります。タイプを指定しない場合、MATLAB はブロックに入力引数が含まれていると仮定します。

詳細については、arguments を参照してください。

引数の検証の例

基本の引数の検証

次の 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 配列。

値の変換

以下の関数は、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

検証関数を使用した特定の制限

検証関数は、より具体的な方法で引数を制限できます。事前定義された検証関数を多くの一般的な種類の検証に使用したり、特定の要件を満たす独自の検証関数を定義することができます。

たとえば、以下の関数は mustBeNumericmustBeRealmustBeMember、およびローカル関数 mustBeEqualSize を使用して、次の検証を指定します。

  • 入力 x は任意の長さの実数値行ベクトルでなければならない。

  • 入力 vx と同じサイズの実数値行ベクトルでなければならない。

  • 入力 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.';
        throwAsCaller(MException(eid,msg))
    end
end

関数の引数の検証は、カスタムの検証関数内では使用しないでください。検証関数の定義の詳細、および事前定義された検証関数のリストについては、引数の検証関数を参照してください。

出力引数の検証

R2022b 以降、引数の検証を出力引数で使用できます。

たとえば、次の関数は、3 つの入力引数と 1 つの出力引数のサイズとクラスを、個別の引数ブロックを使用して検証します。(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. オプションの名前と値の引数

必須の位置引数とオプションの位置引数

位置引数は、特定の順序で関数に渡さなければなりません。引数リスト内で値が渡される位置は、arguments ブロックで引数が宣言される順序に対応していなければなりません。arguments ブロック内の引数名はすべて一意でなければなりません。

arguments ブロック内の位置引数は、引数で既定値が定義されていない限り、関数の呼び出しに際して必要です。引数の宣言で既定値を指定すると、位置関数は任意になります。これは、関数呼び出しで値が渡されない場合、MATLAB は既定値を使用できるためです。

既定値には、定数か、または引数宣言を満たす結果を生成する式を指定できます。式は、arguments ブロック内でそれより前に宣言されている引数を参照できますが、それより後に宣言される引数は参照できません。

MATLAB は、関数呼び出しに引数が含まれていない場合にのみ、既定値の式を評価します。

arguments ブロックでは、すべてのオプションの引数を、すべての必須の引数の後に配置しなければなりません。たとえば、次の引数ブロックでは、maxvalminval は既定値をもつためオプションとなります。

function myFunction(x,y,maxval,minval)
    arguments
        x (1,:) double
        y (1,:) double
        maxval (1,1) double = max(max(x),max(y))
        minval (1,1) double = min(min(x),min(y))
    end

    % Function code
    ....
end

この関数は、次のいずれかの構文を使用して呼び出すことができます。

myFunction(x,y,maxval,minval) 
myFunction(x,y,maxval) 
myFunction(x,y) 

オプションの位置引数は、後続の引数を識別するために関数呼び出し内でその位置を埋める必要がある場合には、必須になります。つまり、minval の値を指定する場合は、maxval の値を指定しなければなりません。

無視される位置引数

MATLAB では、チルダ文字 (~) を引数の代わりに渡すことにより、引数を無視できます。関数シグネチャの引数の位置に対応する arguments ブロック内で、チルダ文字 (~) を追加することで、未使用の位置引数を無視する関数を定義できます。関数シグネチャ内の無視される引数それぞれにチルダ文字 (~) を追加します。

無視される引数は既定値をもつことができず、また、クラス、サイズ、検証関数を指定できません。

チルダ文字 (~) は、その後に必須の位置関数が続いていない場合、オプションの引数として扱われます。たとえば、次の関数ではチルダ文字 (~) はオプションの引数を表します。

function c = f(~)
    arguments
        ~
    end

    % Function code
end

この関数は、引数を指定せずに呼び出すことができます。

c = f 

また、この関数は、1 つの引数を指定して呼び出すこともできます。

c = f(2)

次の関数では、チルダ文字 (~) は必須の引数を表します。

function c = f(~,x)
    arguments
        ~
        x
    end

    % Function code
    ...
end

この関数の呼び出しには、どちらの引数も含まれていなければなりません。

c = f(2,3)

無視される入力を指定した関数呼び出しの詳細については、関数定義の入力の無視を参照してください。

繰り返し引数

繰り返し引数は、引数として繰り返し指定可能な位置引数です。Repeating 属性を含む arguments ブロック内で繰り返し引数を宣言します。

arguments (Repeating)
    arg1
    arg2
    ...
end

関数には、入力用と出力用にそれぞれ 1 つずつ Repeating arguments ブロックを含めることができます。Repeating 入力引数ブロックには 1 つ以上の繰り返し引数を含めることができますが、Repeating 出力引数ブロックには 1 つの繰り返し引数のみ含めることができます。

Repeating arguments ブロックを定義する関数は、ブロック内のすべての引数の 0 回以上の出現で呼び出すことができます。関数の呼び出しに繰り返し引数が含まれる場合、Repeating arguments ブロック内のすべての引数がそれぞれの繰り返しに含まれていなければなりません。

たとえば、Repeating arguments ブロックが入力引数 x および y を定義する場合は、それぞれの繰り返しに xy の両方が含まれていなければなりません。

繰り返し入力引数は既定値を指定できないため、オプションにはできません。ただし、繰り返し引数を含めずに関数を呼び出すことはできます。

関数では、繰り返し入力引数を位置引数の後に、かつ名前と値の引数の前に宣言しなければなりません。名前と値の引数は Repeating ブロック内で指定できません。名前と値の引数の詳細については、名前と値の引数を参照してください。

関数内で、各繰り返し引数は、関数呼び出しで渡される繰り返しの数と等しい数の要素をもつ cell 配列になります。cell 配列の各要素に検証が適用されます。この引数の使用を 0 に指定して関数を呼び出すと、cell 配列のサイズは 1 行 0 列になります。つまり、これは空になります。

たとえば、次の関数では 3 つの繰り返し引数 xy、および option のブロックが宣言されます。

function [xCell,yCell,optionCell] = fRepeat(x,y,option)
    arguments (Repeating)
        x double
        y double
        option {mustBeMember(option,["linear","cubic"])}
    end
    
    % Function code
    % Return cell arrays
    xCell = x;
    yCell = y;
    optionCell = option;
end

入力なし、または 3 の倍数回入力を指定してこの関数を呼び出すことができます。MATLAB は、各引数に対して、その引数に渡されるすべての値を含む cell 配列を作成します。次の fRepeat の呼び出しでは、3 つの繰り返し引数が 2 セット渡されます。

[xCell,yCell,optionCell] = fRepeat(1,2,"linear",3,4,"cubic")
xCell =

  1×2 cell array

    {[1]}    {[3]}


yCell =

  1×2 cell array

    {[2]}    {[4]}


optionCell =

  1×2 cell array

    {["linear"]}    {["cubic"]}

次の関数は、Repeating arguments ブロック内で xy の入力に繰り返し引数を受け入れます。この関数の本体において、繰り返し引数として指定された値は cell 配列 x および y で使用できます。この例では、plot(x1,y1,…) のように x および y の値を交互に配置して、関数 plot に必要な入力に一致させています。

function myPlotRepeating(x,y)
    arguments (Repeating)
        x (1,:) double
        y (1,:) double
    end

    % Function code
    % Interleave x and y
    z = reshape([x;y],1,[]);

    % Call plot function
    if ~isempty(z)
        plot(z{:});
    end
end

引数の繰り返しのペアを指定して、この関数を呼び出します。

x1 = 1:10;
y1 = sin(x1);
x2 = 0:5;
y2 = sin(x2);
myPlotRepeating(x1,y1,x2,y2)

繰り返し引数に varargin を使用しない

引数検証を使用する関数で varargin を使用することは推奨されません。varargin のサイズとクラスが繰り返し引数ブロック内で制限されている場合、この制限は varargin のすべての値に適用されます。

レガシ コードをサポートするために varargin を使用する場合、これは Repeating arguments ブロック内の唯一の引数でなければなりません。

たとえば、次の関数は 2 つの必須の位置引数に加えて、varargin を繰り返し引数として定義します。

function f(a, b, varargin)
    arguments
        a uint32
        b uint32
    end
    arguments (Repeating)
        varargin
    end
    
    % Function code
    ...
end

名前と値の引数

名前と値の引数は、関数に渡される値に名前を関連付けます。名前と値の引数には、次の特徴があります。

  • 任意の順序で関数に渡すことができる

  • 常にオプションである

  • すべての位置引数と繰り返し引数の後に宣言しなければならない

  • Repeating 属性を使用する arguments ブロック内では使用できない

  • 名前と値の構造体を複数使用する場合でも、一意の名前を使用しなければならない

  • 位置引数にも使用されている名前は使用できない

ドット表記を使用して arguments ブロック内で名前と値の引数を宣言し、構造体のフィールドを定義します。たとえば、NameValueArgs という名前の構造体は、2 つの名前と値の引数 Name1 および Name2 を定義します。任意の有効な MATLAB 識別子を構造体名として使用できます。

arguments
    NameValueArgs.Name1
    NameValueArgs.Name2
end

構造体名は関数シグネチャ内になければなりません。

function myFunction(NameValueArgs)

名前と値の構造体のフィールド名を使用して、関数を呼び出します。

myFunction(Name1=value1,Name2=value2)

R2021a より前は、string または文字ベクトルとして名前を渡し、名前と値をコンマで区切ります。両方の構文は以降のリリースでも有効です。

関数シグネチャ内で使用される構造体の名前は、関数に渡される名前と値を含む関数ワークスペース内の構造体の名前です。

function result = myFunction(NameValueArgs)
    arguments
        NameValueArgs.Name1
        NameValueArgs.Name2
    end

    % Function code
    result = NameValueArgs.Name1 * NameValueArgs.Name2;
end
r = myFunction(Name1=3,Name2=7)
r =

    21

あいまいさがない場合は、名前と値の引数は名前の部分一致をサポートします。たとえば、LineWidth および LineStyle を 2 つの名前と値の引数として定義する関数は、LineWLineS を受け入れますが、Line を使用するとエラーになります。一般に、コードの可読性を向上させ、予期しない動作を回避するために、完全名を使用することが推奨されます。

関数呼び出しで同じ名前と値の引数をエラーなしで繰り返すことができますが、指定される最新バージョンは MATLAB が受け入れるバージョンです。たとえば、以下の plot の呼び出しでは、Color の値が 2 回指定されています。MATLAB はプロットを赤色で表示します。

plot(x,y,Color="blue",LineStyle="--",Color="red")

名前と値の引数の既定値

それぞれの名前に既定値を指定できます。既定値を指定せずに、その名前と値の引数なしで関数が呼び出される場合、そのフィールドは名前と値の構造体に存在しません。名前と値の引数が関数に渡されない場合、MATLAB は構造体を作成しますが、そこにフィールドはありません。

関数呼び出しで渡された名前と値の引数を特定するには、関数 isfield を使用します。

たとえば、次の関数は 2 つの必須の位置引数 (widthheight) および 2 つの名前と値の引数 (LineStyleLineWidth) を定義します。この例では、options 構造体には 2 つのフィールド (LineStyleLineWidth) があり、既定値か、または関数の呼び出し時に名前と値の引数として指定された値が含まれています。

function myRectangle(width,height,options)
    arguments
        width double
        height double
        options.LineStyle (1,1) string = "-"
        options.LineWidth (1,1) {mustBeNumeric} = 1
    end

    % Function code
    ...
end

以下の構文はすべて、この関数を呼び出す有効な方法です。

myRectangle(4,5)
myRectangle(4,5,LineStyle=":",LineWidth=2)
myRectangle(4,5,LineWidth=2,LineStyle=":")
myRectangle(4,5,LineStyle=":")
myRectangle(4,5,LineWidth=2)

R2021a より前は、string または文字ベクトルとして名前を渡し、名前と値をコンマで区切ります。以下に例を示します。

myRectangle(4,5,"LineStyle",":","LineWidth",2)
myRectangle(4,5,"LineWidth",2,"LineStyle",":")

繰り返し引数および名前と値の引数の使用

関数で繰り返し引数が定義されている場合、繰り返し引数ブロックに続く別の arguments ブロック内で名前と値の引数を宣言しなければなりません。たとえば、次の関数は 2 つの繰り返し引数 xy を受け入れます。xy の繰り返しをすべて指定した後に、値 lin または log を名前 PlotType に代入する名前と値の引数を指定できます。

関数呼び出しに PlotType 引数が含まれるかどうかを判定するには、関数 isfield を使用して scale 構造体の PlotType フィールドをチェックします。

function myLinLog(x,y,scale)
    arguments(Repeating)
        x (1,:) double
        y (1,:) double
    end
    arguments
        scale.PlotType (1,1) string
    end
    z = reshape([x;y],1,[]);
    if isfield(scale,"PlotType")
        if scale.PlotType == "lin"
            plot(z{:})
        elseif scale.PlotType =="log"
            loglog(z{:})
        end
    end
end

名前と値の引数を指定して、または指定せずに、この関数を呼び出します。

myLinLog(1:5,1:5)
myLinLog(1:5,1:5,1:10,1:100:1000)
myLinLog(1:5,1:5,1:10,1:100:1000,PlotType="log")

R2021a より前は、string または文字ベクトルとして名前を渡し、名前と値をコンマで区切ります。以下に例を示します。

myLinLog(1:5,1:5,1:10,1:100:1000,"PlotType","log")

複数の名前と値の構造体

関数の引数ブロックには、複数の名前と値の構造体を含めることができます。ただし、フィールド名は構造体全体で一意でなければなりません。以下の関数には、lineOptionsfillOptions という 2 つの名前と値の構造体があります。これらの構造体は同じフィールド名をもつことができません。

関数 myRectangle の引数は次のとおりです。

  • widthheightdouble 型の必須の位置引数である。

  • lineOptions.LineStyle は既定値 "-" をもつスカラー string である。

  • lineOptions.LineWidth は既定値 1 をもつスカラー数値である。

  • fillOptions.Color は string である。

  • fillOptions.Pattern には値の制限がない。

function myRectangle(width,height,lineOptions,fillOptions)
    arguments
        width double
        height double
        lineOptions.LineStyle (1,1) string = "-"
        lineOptions.LineWidth (1,1) {mustBeNumeric} = 1
        fillOptions.Color string
        fillOptions.Pattern
    end

    % Function Code
    ...
end

名前と値の引数のロバストな処理

関数に名前と値の引数を実装するためのベスト プラクティスは、その引数を引数ブロックで定義することです。引数ブロックでは、名前と値の引数を解析するための独自コードを作成する必要がなく、"name",value 構文と R2021a で導入された name=value 構文の両方に対応するロバストな引数解析を実装できます。

有効な名前の適用

引数ブロックで名前と値の引数を定義すると、名前が確実に有効な識別子になります。これにより、引数が "name",valuename=value の両方の構文で確実に機能するようになります。たとえば、無効な識別子を使用している名前と値の引数は、コンマ区切りの構文では機能できます。

myFunction(data,"allow-empty",true)
ただし、allow-empty=true を使用した同じ呼び出しでは、エラーがスローされます。引数ブロックで名前と値の引数を定義すると、定義した名前が確実に有効な MATLAB 変数名になり、name=value 構文に適合します。

テキスト入力での予期しない結果の回避

オプションのテキスト入力および名前と値の引数の両方を含む関数では、MATLAB によってテキスト入力が名前と値の引数の名前として解釈されるおそれがあります。次の関数には、2 つのオプションのテキスト入力と 1 つの名前と値の引数が含まれています。

function mySignal(tag,unit,opts)
    arguments
        tag = "0"
        unit = "ampere"
        opts.Magnifier {mustBeMember(opts.Magnifier,["small","medium","big"])}
    end
end
ユーザーが、tag の値を "Mag"unit の値を "coulomb" に設定するつもりで、次の関数呼び出しを入力します。
mySignal("Mag","coulomb")
しかし、MATLAB は、部分一致によって "Mag" を名前と値の引数 Magnifer として解析します。"coulomb" はその名前に対して有効な値ではないため、この関数はエラーになります。

これを回避する方法の 1 つとして、tag の既定値を削除してそれを必須の引数にする方法があります。

function mySignal(tag,unit,opts)
    arguments
        tag
        unit = "ampere"
        opts.Magnifier {mustBeMember(opts.Magnifier,["small","medium","big"])}
    end
end
MATLAB は必須の入力を名前と値の引数として解析しないため、今回は同じ関数呼び出しで tag の値が "Mag" に設定され、エラーは発生しません。

もう 1 つの方法として、3 つすべての入力を名前と値の引数にする方法があります。これにより、各値が名前に関連付けられるため、ユーザーは入力を指定するときに誤りを回避でき、ユーザーが入力を指定する順序は最終結果に影響しません。

クラス プロパティからの名前と値の引数

MATLAB には、クラスのパブリック プロパティを名前と値の引数の名前に使用する便利な関数構文があります。クラスで定義されたすべての設定可能なプロパティ (つまり、パブリックの SetAccess をもつすべてのプロパティ) に名前と値の引数を指定するには、arguments ブロックで次の構文を使用します。

structName.?ClassName

関数は、"structName.? ClassName" 構文を 1 回だけ使用できます。したがって、関数は、異なるクラスと構造体名を使用する場合でも、クラスからフィールド名を取得する名前と値の構造体は 1 つしか定義できません。

クラスでプロパティ検証を使用して、プロパティに代入できる値を制限している場合、関数はその検証を個々の名前と値の引数に適用します。プロパティ検証の詳細については、プロパティ値の検証を参照してください。

たとえば、次の関数は 2 つの必須の引数 xy をもち、matlab.graphics.chart.primitive.Bar クラスの任意のパブリック プロパティ名と値を受け入れます。

function myBar(x,y,propArgs)
    arguments
        x (:,:) double
        y (:,:) double
        propArgs.?matlab.graphics.chart.primitive.Bar
    end
    propertyCell = namedargs2cell(propArgs);
    bar(x,y,propertyCell{:})
end

必須の入力と、任意の設定可能なプロパティの名前と値のペアを指定して、関数を呼び出します。

x = [1,2,3;4,5,6];
y = x.^2;
myBar(x,y)
myBar(x,y,FaceColor="magenta",BarLayout="grouped")

R2021a より前は、string または文字ベクトルとして名前を渡し、名前と値をコンマで区切ります。以下に例を示します。

myBar(x,y,"FaceColor","magenta","BarLayout","grouped")

特定のプロパティのオーバーライド

arguments ブロック内で、プロパティ名を特定の名前と値の引数で再定義することにより、クラスのプロパティ検証をオーバーライドできます。

structName.?ClassName
structName.PropertyName (dim1,dim2,...) ClassName {fcn1,fcn2,...}

特定の名前と値の引数の検証は、個別に指定されたプロパティ名に対しクラスで定義された検証をオーバーライドします。

たとえば、以下の関数は名前と値の引数を matlab.graphics.chart.primitive.Bar クラスのプロパティとして定義します。また、この関数は、特定の値 red または blue のみが許可されるように、プロパティ名 FaceColor をオーバーライドします。

matlab.graphics.chart.primitive.Bar クラスでの FaceColor の既定値は、制限された値 (red または blue) のいずれでもありません。したがって、オーバーライドする宣言では、検証関数 mustBeMember によって課された制限を満たす既定値を代入しなければなりません。つまり、既定値は red または blue でなければなりません。

この関数は関数 namedargs2cell を使用して、名前と値の構造体を、交互に配置された名前と値を含む cell 配列に変換します。

function myBar(x,y,propArgs)
    arguments
        x (:,:) double
        y (:,:) double
        propArgs.?matlab.graphics.chart.primitive.Bar
        propArgs.FaceColor {mustBeMember(propArgs.FaceColor,{'red','blue'})} = "blue"
    end
    propertyCell = namedargs2cell(propArgs);
    bar(x,y,propertyCell{:})
end

2 つの必須の引数 xy を使用して関数を呼び出します。オプションで、関数 bar でサポートされる任意の名前と値のペアと、FaceColor の値 (red または blue のいずれか) を渡します。FaceColor の他の値は許可されません。

x = [1,2,3;4,5,6];
y = x.^2;
myBar(x,y)
myBar(x,y,FaceColor="red",BarLayout="grouped")

引数の検証の順序

関数が呼び出されると、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 および buint32 値に変換した後、既定値を評価して c に代入します。この場合、変換の結果、どちらの入力の値も 2 になります。したがって、ab の積は 4 になります。

c =

  uint32

   4

3 番目の入力に値を指定する場合、関数は値を c に代入し、既定値の式は評価しません。

c = f(1.8,1.5,25)
c =

  uint32

   25

クラスとサイズの変換の回避

関数に渡される引数の値が検証に必要なクラスとサイズに一致しない場合、MATLAB は、変換が可能であれば、その値を宣言されたクラスとサイズに変換します。引数の検証において、MATLAB によって実行される標準の変換を避けるには、クラスおよびサイズの制限の代わりに検証関数を使用します。検証関数の呼び出しは値を返さず、引数の値を変更することはできません。

たとえば、次の関数は最初の入力を、double クラスである任意サイズの 2 次元配列に制限します。2 番目の入力は、任意のクラスの 5 行 3 列の配列でなければなりません。

function f(a,b)
    arguments
        a (:,:) double
        b (5,3)
    end
    % Function code
end

MATLAB の標準の型変換とスカラー拡張のため、次の入力を指定してこの関数を呼び出しても検証エラーを受け取ることはありません。

f('character vector',144)

既定で、MATLAB は文字ベクトルの要素を等価な数値に変換し、スカラー拡張を適用してスカラー値 144 から 5 行 3 列の配列を作成します。

特殊な検証関数を使用して、より具体的な引数の検証を行うことができます。たとえば、この関数は、最初と 2 番目の引数に関するクラスとサイズの仕様の代わりに使用する、特殊な検証関数を定義します。これらのローカル関数によって、入力値の変換を回避できるようになります。

  • mustBeOfClass は入力を特定のクラスに制限し、変換またはサブクラスを許可しません。関連する関数については、mustBeA を参照してください。

  • mustBeEqualSize は 2 つの入力を等しいサイズに制限し、スカラー拡張を許可しません。関連する関数については、mustBeScalarOrEmpty を参照してください。

  • mustBeDims は入力を指定された次元に制限し、転置やスカラー拡張を許可しません。関連する関数については、mustBeVector を参照してください。

function fCustomValidators(a,b)
    arguments
        a {mustBeOfClass(a,'double'), mustBeDims(a,2)}
        b {mustBeEqualSize(b,a)}
    end
    % Function code
end

% Custom validator functions
function mustBeOfClass(input,className)
    % Test for specific class name
    cname = class(input);
    if ~strcmp(cname,className)
        eid = 'Class:notCorrectClass';
        msg = ['Input must be of class ',className,'.'];
        throwAsCaller(MException(eid,msg))
    end
end

function mustBeEqualSize(a,b)
    % Test for equal size
    if ~isequal(size(a),size(b))
        eid = 'Size:notEqual';
        msg = 'Inputs must have equal size.';
        throwAsCaller(MException(eid,msg))
    end
end

function mustBeDims(input,numDims)
    % Test for number of dimensions    
    if ~isequal(length(size(input)),numDims)
        eid = 'Size:wrongDimensions';
        msg = ['Input must have ',num2str(numDims),' dimension(s).'];
        throwAsCaller(MException(eid,msg))
    end
end

fCustomValidators を使用して関数 mustBeOfClass をテストします。最初の引数がクラス double ではない場合、関数はエラーを返します。

fCustomValidators('character vector',144)
Error using fCustomValidators
 fCustomValidators('character vector',144)
                   ↑
Invalid argument at position 1. Input must be of class double.

この呼び出しでは、最初の引数の次元数が正しくないため、検証関数はカスタム エラー メッセージを返します。

fCustomValidators(ones(2,2,4),144)
Error using fCustomValidators
 fCustomValidators(ones(2,2,4),144)
                   ↑
Invalid argument at position 1. Input must have 2 dimension(s).

mustBeEqualSize 検証関数は、入力が同じサイズかどうかを確認します。

fCustomValidators(ones(2,2),144)
Error using fCustomValidators
 fCustomValidators(ones(2,2),144)
                             ↑
Invalid argument at position 2. Inputs must have equal size.

関連する事前定義された検証関数については、mustBeAmustBeFloat および mustBeVector を参照してください。

引数の検証での nargin

関数 nargin は、現在実行中の関数の呼び出し時に渡された関数入力引数の数を返します。関数の引数の検証を使用する場合、関数内で nargin から返される値は、関数の呼び出し時に指定された位置引数の数です。

繰り返し引数は位置引数であるため、関数の呼び出し時に渡された繰り返し引数の数は nargin で返される値に含まれます。

nargin が返す値には、関数呼び出しに含まれていないオプションの引数は含まれません。また、nargin は名前と値の引数をカウントしません。

関数の呼び出し時にオプションの位置引数が渡されるかどうかを判定するには、nargin を使用します。たとえば、次の関数は 3 つの位置引数と 1 つの名前と値の引数を宣言します。呼び出しに際して渡される引数を関数がどのように判定するかを以下に示します。

  • nargin は、オプションの位置引数 c が関数に渡されるかどうかを switch ブロックで判定。

  • isfield は、Format の名前と値の引数が関数に渡されるかどうかを判定。

function result = fNargin(a,b,c,namedargs)
    arguments
        a (1,1) double
        b (1,1) double
        c (1,1) double = 1
        namedargs.Format (1,:) char
    end

    % Function code
    switch nargin
        case  2
            result = a + b;
        case 3
            result = a^c + b^c;
    end
    if isfield(namedargs,"Format")
        format(namedargs.Format);
    end
end

この関数呼び出しでは、nargin の値は 2 です。

result = fNargin(3,4)
result =

     7

この関数呼び出しでは、nargin の値は 3 です。

result = fNargin(3,4,7.62)
result =

   4.3021e+04

この関数呼び出しでは、nargin の値は 3 です。

result = fNargin(3,4,7.62,Format="bank")
result =

      43020.56

変数および関数へのアクセスの制限

arguments ブロックは関数のワークスペース内にあります。import コマンドを使用して関数のスコープに追加されたパッケージ、クラスまたは関数はすべて、arguments ブロックのスコープに追加されます。

検証関数と既定値の式から参照できる変数は、既に宣言されている入力変数のみです。次の関数では、c の既定値は ab から派生します。

function c = f(a,b,c)
    arguments
        a uint32
        b uint32
        c uint32 = a * b
    end
 
    % Function code
    ...
end

しかし、arguments ブロックでまだ宣言されていない入力変数は、参照できません。たとえば、前の関数で次の宣言を引数 a に使用することは有効ではありません。これは、bc がまだ宣言されていないためです。

arguments
    a uint32 = b * c
    b uint32
    c uint32
end

引数の検証の式は、先に宣言された引数、つまり検証済みの引数のみを参照できます。検証関数と、名前と値の引数の既定値は、他の名前と値の引数にアクセスできません。

arguments ブロック内の関数の制限

先に宣言された変数への参照はすべて、検証関数と既定値のテキスト内で可視でなければなりません。コードの透明性を確保するため、関数ワークスペースとやり取りする関数は使用しないでください。具体的には、入れ子関数や次の表にリストされている関数を arguments ブロックで使用しないでください。

assigninbuiltinclear
dbstackevalevalc
evalinexistfeval
inputinputnameload
narginnarginchknargoutchk
savewhoswho

これらの制限は、arguments ブロック内でのみ適用され、関数本体の変数や関数には適用されません。

引数ブロックのデバッグ

引数ブロック内でデバッグしている間、ワークスペースは "読み取り専用" になります。つまり、ワークスペースを確認したり、変数に割り当てられた値を表示したりすることはできます。ただし、ワークスペースが読み取り専用の間に、新しい変数を作成したり、既存の変数に割り当てられた値を変更したりすることはできません。デバッガーが引数ブロックの範囲外になると、再び変数の作成または編集が可能になります。

参考

|

関連するトピック