Main Content

名前と値の引数の検証

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

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

  • 常にオプションである

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

  • 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 ブロックに続く別の 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

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

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

有効な名前の適用

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

myFunction(data,"allow-empty",true)
ただし、allow-empty=true を使用した同じ呼び出しでは、エラーがスローされます。arguments ブロックで名前と値の引数を定義すると、定義した名前が確実に有効な 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")

参考

|

関連するトピック