Main Content

R2019b での関数の優先順位の変更に対するコードの更新

R2019b 以降、MATLAB では名前の解決に関する規則が変更されており、変数、入れ子関数、ローカル関数、および外部関数の優先順位が影響を受けます。新しい規則により、名前の解決が単純化され標準化されます。詳細については、関数の優先順位を参照してください。

これらの変更により、関数 import の動作が影響を受けます。コードを解析し、場合によっては更新する必要があります。最初に、コードの import ステートメントを検索します。たとえば、ファイルの検索を使用して、テキスト import を含む .m ファイルと .mlx ファイルを検索します。以下の変更による影響を評価する際には、これらの検索結果を参照してください。

1 つの関数内で識別子を 2 つの目的に使用することはできない

R2019b 以降、識別子をまずローカル関数またはインポートされた関数として使用し、次に変数として使用すると、エラーが発生します。以前のリリースでは、識別子は関数のスコープ内で異なる目的に使用可能であり、その結果あいまいなコードにつながりました。

この動作変更がコードに影響する場合は、変数か関数の名前を変更して、これらが異なる名前をもつようにします。

R2019b 以降更新されたコードR2019a 以前

名前 local が関数 local として使用され、その後変数として使用されています。このコードではエラーが発生します。

function myfunc
% local is an undefined variable
local(1); % Errors
local = 2; 
disp(local);
end

function local(x)
disp(x)
end

関数 local の名前を localFcn に変更します。

function myfunc
localFcn(1);
local = 2; 
disp(local);
end

function localFcn(x)
disp(x)
end

このコードは 1 を表示し、次に 2 を表示します。

function myfunc
local(1); % local is a function
local = 2; 
disp(local);
end

function local(x)
disp(x)
end

明示的な宣言のない識別子は変数として扱われないことがある

R2019b 以降、MATLAB® ではプログラム内の変数の識別にインデックス演算子を使用しません。以前は、明示的な宣言のない識別子は、コロン、end、または中かっこでインデックス付けされた場合、変数として扱われました。たとえば、x(a,b,:)x(end)x{a} において x は変数として扱われました。

以下のコードを考えます。コロンのインデックスがあるため、MATLAB で x は変数として扱われていました。R2019b 以降、パス上に同名の関数が存在する場合、MATLAB では x を関数として扱います。

function myfunc
load data.mat; % data.mat contains variable x
disp(x(:))
end

x を関数ではなく data.mat の変数として使用する場合は、その旨を明示的に宣言します。同様に、識別子 x をスクリプトから取得した変数として使用するには、そのスクリプトを呼び出す前に宣言します。この新しい動作は、関数 simevalevalc、および assignin で変数が暗黙的に導入された場合にも適用されます。

次の表は、コードの更新方法の例をいくつか示しています。

更新前更新後
function myfunc
load data.mat;
disp(x(:))
end
function myfunc
load data.mat x;
disp(x(:))
end
function myfunc2
myscript; % Contains variable x
disp(x(:))
end
function myfunc2
x = [];
myscript;
disp(x(:))
end

変数は、親関数と入れ子関数の間で暗黙的に共有できない

R2019b 以降、識別子が親関数内で変数として明示的に宣言されている場合にのみ、識別子を入れ子関数とその親関数間で変数として共有できます。

たとえば以下のコードでは、myfunc 内の識別子 x は入れ子関数内の変数 x とは異なります。x がパス上の関数である場合、MATLAB は myfunc 内の x を関数として扱い、コードを実行します。そうでない場合、MATLAB はエラーをスローします。

function myfunc
nested;
x(3) % x is not a shared variable
    function nested
    x = [1 2 3];
    end
end

以前のリリースでは、x がパス上の関数である場合、MATLAB はこれを myfunc 内では関数として扱い、nested 内では変数として扱いました。x がパス上の関数ではない場合、MATLAB は myfuncnested の間で共有される変数として扱いました。その結果、コードの出力はパスの状態に依存することになりました。

親関数と入れ子関数間で共有される変数として識別子を使用するには、コードの更新が必要な場合があります。たとえば、親関数内で識別子を空の配列に初期化できます。

更新前更新後
function myfunc
nested;
x(3)
    function nested
    x = [1 2 3];
    end
end
function myfunc
x = [];
nested;
x(3)
    function nested
    x = [1 2 3];
    end
end

ワイルドカードベースのインポートでの優先順位の変更

R2019b 以降、ワイルドカードベースのインポートによりインポートされた関数は、変数、入れ子関数、およびローカル関数より優先順位が低くなります。R2019a 以前は、関数内のインポートは、ローカル関数や入れ子関数より優先されました。

たとえば次のコードでは、ステートメント local() は、ワイルドカードベースのインポートで pkg1.local ではなく myfunc/local を呼び出します。ステートメント nest()pkg1.nest ではなく myfunc/nest を呼び出します。

R2019b 以降R2019a 以前
function myfunc
% Import includes functions local and nest
import pkg1.* 
local()   % Calls myfunc/local 

    function nest
    end

nest();   % Calls myfunc/nest 
end

function local
end
function myfunc
% Import includes functions local and nest
import pkg1.* 
local()   % Calls pkg1.local and 
          % displays warning since R2018a

    function nest
    end

nest();   % Calls pkg1.nest
end

function local
end

import の検索結果で、ワイルドカード文字 (*) を含むステートメントを探してください。

完全修飾のインポート関数は、入れ子関数と同じ名前をもつことができない

R2019b 以降、完全修飾インポートが同じスコープ内の入れ子関数と名前を共有する場合、エラーがスローされます。

R2019b 以降更新されたコードR2019a 以前

この関数は同じスコープ内の入れ子関数と名前を共有するためエラーになります。

function myfunc
import pkg.nest  % Errors 
nest();          

    function nest
    end
end

関数 nestimport ステートメントから呼び出すために、ローカル関数 myfunc/nest の名前を変更します。

function myfunc
import pkg.nest 
nest();          

    function newNest
    end
end

この関数は関数 nestimport ステートメントから呼び出します。

function myfunc
import pkg.nest   
nest();  % Calls pkg.nest

    function nest
    end
end

インポートされた関数 nest と同名の変数を宣言することはサポートされないため、この関数はエラーになります。

function myvarfunc
import pkg.nest  % Errors 
nest = 1
end

変数 nest の名前を変更します。

function myvarfunc
import pkg.nest  % Errors 
thisNest = 1
end

この関数は変数 nest を変更します。

function myvarfunc
import pkg.nest
nest = 1  % Modifies variable nest and
          % displays warning since R2018a
end

完全修飾のインポートは、同名の外部スコープ定義より優先される

R2019b 以降、完全修飾インポートは常に、同名の外部スコープ定義より優先されます。R2019a 以前は、外部スコープ内の識別子よりも優先される完全修飾インポートは無視されました。

R2019b 以降更新されたコードR2019a 以前

ローカル関数 nest は、インポートされたパッケージから関数 x を呼び出します。

function myfunc
x = 1;

    function nest
        % Import function x
        import pkg1.x 
        % Calls pkg1.x 
        x()
    end
end

変数 x をローカル関数 nest で使用するには、この変数を引数として渡します。

function myfunc
x = 1;
nest(x)

    function nest(x1)
        % Import function x
        import pkg1.x 
        % Calls pkg1.x with 
        % variable x1
        x(x1)
    end
end

このコードでは、関数 nest はインポートされた関数 x を無視します。

function myfunc
x = 1;

    function nest
        % Import function x
        import pkg1.x
        % x is a variable
        x()
    end
end

インポートが見つからない場合のエラー処理

R2019b 以降、Java® の有無に関係なく、解決できない完全修飾インポートはエラーをスローします。R2019a 以前は、-nojvm オプションを指定して MATLAB を起動したかどうかによって、MATLAB の動作が異なりました。エラー メッセージをカスタマイズするために javachkusejava などの関数は使用しないでください。

R2019b 以降更新されたコードR2019a 以前

-nojvm オプションを指定して MATLAB を起動すると、このコードはエラーをスローします。

function myfunc 
import java.lang.String % Errors

if ~usejava('jvm') 
    % Statement never executes
    disp('This function requires Java'); 
else 
    % Do something with Java String class 
end 
end

usejava の呼び出しを削除します。

function myfunc 
import java.lang.String % Errors
% Do something with java String class 
end

-nojvm オプションを指定して MATLAB を起動すると、このコードはメッセージを表示します。

function myfunc 
import java.lang.String 

if ~usejava('jvm') 
    % Display message
    disp('This function requires Java'); 
else 
    % Do something with Java String class 
end 
end

入れ子関数は親関数から import ステートメントを継承する

R2019b 以降、入れ子関数は親関数から import ステートメントを継承します。R2019a 以前は、入れ子関数は親関数から import ステートメントを継承しませんでした。

R2019b 以降R2019a 以前
function myfunc

% Package p1 has functions plot and bar
import p1.plot 
import p1.*
nest

    function nest
        plot   % Calls p1.plot
        bar    % Calls p1.bar
    end
end
function myfunc

% Package p1 has functions plot and bar
import p1.plot 
import p1.*
nest

    function nest
        plot   % Calls plot function on path
        bar    % Calls bar function on path
    end
end

複合名解決の優先順位の変更

R2019b 以降、MATLAB は異なったやり方で複合名を解決します。複合名はドットでつながれた複数の部分で構成されており (たとえば、a.b.c)、パッケージ メンバーの参照に使用できます。R2019b では、MATLAB は最も長く一致する接頭辞を優先することで、複合名を解決します。以前のリリースでは、優先順位はより複雑な一連の規則に従っていました。

たとえば、パッケージ pkg に、静的メソッド bar をもつクラス foo と、関数 bar をもつサブパッケージ foo が含まれているとします。

+pkg/@foo/bar.m % bar is a static method of class foo
+pkg/+foo/bar.m % bar is a function in subpackage foo

R2019b では、which pkg.foo.bar の呼び出しはパッケージ関数へのパスを返します。

which pkg.foo.bar
+pkg/+foo/bar.m

以前は、パッケージとクラスが同じ名前をもつ場合、静的メソッドがパッケージ関数より優先されました。

無名関数は解決済みの識別子と未解決の識別子を含むことができる

R2019b 以降、無名関数に解決済みの識別子と未解決の識別子の両方を含めることができます。以前のリリースでは、無名関数内のいずれかの識別子が作成時に解決されなかった場合、その無名関数内のすべての識別子が未解決になりました。

R2019b 以降R2019a 以前

無名関数を評価するために、MATLAB は、myscript で定義された x を指定してローカル関数 lf を呼び出します。これは、無名関数内の lf がローカル関数に解決されるためです。

function myfun
myscript; % Includes x = 1 and lf = 10
f = @()lf(x);
f()       % Displays 'Inside lf'
end

% Local function to myfun
function lf(y) 
disp('Inside lf');
end 

MATLAB は lfx とともに未解決の識別子と見なし、x を使用して、myscript からの変数 lf にインデックスを付けました。

function myfun
myscript; % Includes x = 1 and lf = 10
f = @()lf(x);
f()       % Displays 10
end

% Local function to myfun
function lf(y) 
disp('Inside lf');
end 

参考

関連するトピック