Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

入れ子関数

入れ子関数とは

入れ子関数は、親関数内に完全に含まれている関数です。プログラム ファイル内の関数は、入れ子関数を含むことができます。

たとえば、parent という以下の関数は、nestedfx という入れ子関数を含んでいます。

function parent
disp('This is the parent function')
nestedfx

   function nestedfx
      disp('This is the nested function')
   end

end

入れ子関数と他の種類の関数の主な違いは、入れ子関数は自身の親関数で定義された変数にアクセスして変更できるということです。その結果、

  • 入れ子関数は、入力引数として明示的に渡されていない変数を使用できます。

  • 親関数で、入れ子関数の実行に必要なデータをもつ入れ子関数のハンドルを作成できます。

入れ子関数の必要条件

  • 通常、関数には end ステートメントは不要です。ただし、プログラム ファイルで関数を入れ子にするには、そのファイル内の "すべての" 関数で end ステートメントを使用しなければなりません。

  • if/elseif/elseswitch/caseforwhiletry/catch など、MATLAB® の任意のプログラム コントロール ステートメント内で、 入れ子関数を定義することはできません。

  • 入れ子関数は (feval を使用せずに) 名前で直接呼び出すか、または (str2func ではなく) @ 演算子を使って作成した関数ハンドルで呼び出さなければなりません。

  • 入れ子関数またはそれを含む関数内の変数は、すべて明示的に定義しなければなりません。したがって、変数に値を代入する関数やスクリプトを呼び出すには、関数ワークスペースにその変数が既に存在していなければなりません。(詳細は、エラーの解決: 静的なワークスペースへの変数追加の試みを参照)

親関数と入れ子関数間での変数の共有

一般に、ある関数ワークスペース内の変数を別の関数で使用することはできません。ただし、入れ子関数は、自身を含む関数のワークスペースにある変数にアクセスして変更することができます。

つまり、入れ子関数と親関数の双方は、同じ変数を引数として渡すことなく変更できます。たとえば、関数 main1 および main2 のそれぞれでは、メイン関数と入れ子関数ともに変数 x にアクセスできます。

function main1
x = 5;
nestfun1

   function nestfun1 
     x = x + 1;
   end 

end
function main2
nestfun2

   function nestfun2
      x = 5;
   end 
   
x = x + 1;
end

所定の変数が親関数で使用されない場合は、入れ子関数のローカル変数として扱われます。たとえば次の関数 main では、2 つの入れ子関数にそれぞれ独自バージョンの x があり、その相互対話は不可能です。

function main
   nestedfun1
   nestedfun2

   function nestedfun1
      x = 1;
   end

   function nestedfun2
      x = 2;
   end
end

出力引数を返す関数は、ワークスペースに出力用の変数をもっています。ただし、親関数は、入れ子関数の出力変数を明示的に要求した場合のみ、その出力変数をもちます。たとえば、この関数 parentfun は、ワークスペースに変数 y"もちません"

function parentfun
x = 5;
nestfun;

   function y = nestfun
     y = x + 1;
   end 

end

コードを以下のように変更すると、変数 zparentfun のワークスペースに入るようにます。

function parentfun
x = 5;
z = nestfun;

   function y = nestfun
     y = x + 1;
   end 

end

ハンドルを使用した関数パラメーターの格納

入れ子関数は 3 つのソースから変数を使用できます。

  • 入力引数

  • その入れ子関数内で定義された変数

  • 親関数で定義された変数。"スコープ外の" 変数とも呼ばれます。

入れ子関数の関数ハンドルを作成する場合、そのハンドルはその関数名のほかに、スコープ外の変数の値も格納します。

たとえば、makeParabola.m というファイルに新しい関数を作成します。この関数はいくつかの多項式係数を受け取り、その多項式の値を計算する入れ子関数のハンドルを返します。

function p = makeParabola(a,b,c)
p = @parabola;

   function y = parabola(x)
   y = a*x.^2 + b*x + c;
   end

end

関数 makeParabola は、係数 ab および c の値を含む関数 parabola のハンドルを返します。

コマンド ラインで、係数値 1.3.2 および 30 を指定して関数 makeParabola を呼び出します。返された関数ハンドル p を使用して特定の点で多項式を評価します。

p = makeParabola(1.3,.2,30);

X = 25;
Y = p(X)
Y =
  847.5000

多くの MATLAB 関数は関数ハンドル入力を受け取って値の範囲で関数を評価します。たとえば、放物型方程式を -25+25 の範囲でプロットします。

fplot(p,[-25,25])

さまざまな多項式係数を使用する複数の関数 parabola のハンドルを作成できます。

firstp = makeParabola(0.8,1.6,32);
secondp = makeParabola(3,4,50);
range = [-25,25];

figure
hold on
fplot(firstp,range)
fplot(secondp,range,'r:')
hold off

入れ子関数の可視性

それぞれの関数には、一定の "スコープ" があります。スコープとは、その関数から見える一連の他の関数です。入れ子関数は、以下の方法で使用できます。

  • 入れ子関数の 1 つ上のレベルから呼び出す (次のコードでは、関数 AB または D は呼び出せますが、CE は呼び出せません)。

  • 同じ親関数内にある同じレベルの入れ子関数から呼び出す (関数 BD を、そして DB を呼び出せます)。

  • 下位レベルの関数から呼び出す (関数 CB または D を呼び出せますが、E は呼び出せません)。

    function A(x, y)              % Main function
    B(x,y)
    D(y)
    
       function B(x,y)            % Nested in A
       C(x)
       D(y)
    
          function C(x)           % Nested in B
          D(x)
          end
       end
    
       function D(x)              % Nested in A
       E(x)
    
          function E(x)           % Nested in D
          disp(x)
          end
       end
    end

入れ子関数のスコープを拡張する最も簡単な方法は、ハンドルを使用した関数パラメーターの格納で説明されているように、関数ハンドルを作成してそれを出力引数として返すことです。入れ子関数を呼び出すことができる関数のみが、入れ子関数へのハンドルを作成できます。

関連するトピック