Update Code for R2019b Changes to Function Precedence Order - MATLAB & Simulink (original) (raw)

Starting in R2019b, MATLAB changes the rules for name resolution, impacting the precedence order of variables, nested functions, local functions, and external functions. The new rules simplify and standardize name resolution. For more information, see Function Precedence Order.

These changes impact the behavior of the import function. You should analyze and possibly update your code. To start, search your code for import statements. For example, use Find Files to search for .m and .mlx files containing text import. Refer to these search results when evaluating the effects of the following changes.

Identifiers cannot be used for two purposes inside a function

Starting in R2019b, an error results if you use an identifier, first as a local or imported function, and then as a variable. In previous releases, an identifier could be used for different purposes within the scope of a function, which resulted in ambiguous code.

If this behavior change impacts your code, rename either the variable or the function so that they have different names.

Starting in R2019b Updated Code R2019a and Earlier
The name local is used as the local function and then a variable. This code errors.function myfunc % local is an undefined variable local(1); % Errors local = 2; disp(local); end function local(x) disp(x) end Rename the function local to localFcn.function myfunc localFcn(1); local = 2; disp(local); end function localFcn(x) disp(x) end This code displays 1 then 2.function myfunc local(1); % local is a function local = 2; disp(local); end function local(x) disp(x) end

Identifiers without explicit declarations might not be treated as variables

Starting in R2019b, MATLAB® does not use indexing operators to identify the variables in your program. Previously, an identifier without an explicit declaration was treated as a variable when it was indexed with a colon, end, or curly braces. For example, x was treated as a variable in x(a,b,:), x(end), and x{a}.

Consider the following code. MATLAB used to treat x as a variable because of colon-indexing. Starting in R2019b, if a function of the same name exists on the path, MATLAB treats x as a function.

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

If you intend to use x as a variable from data.mat instead of a function, explicitly declare it. Similarly, to use an identifier x as a variable obtained from a script, declare it before invoking the script. This new behavior also applies if the variable is implicitly introduced by the functions sim, eval, evalc, and assignin.

This table shows some examples of how you can update your code.

Before After
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

Variables cannot be implicitly shared between parent and nested functions

Starting in R2019b, sharing an identifier as a variable between a nested function and its parent function is possible only if the identifier is explicitly declared as a variable in the parent function.

For example, in the following code, identifier x inmyfunc is different from variable x in the nested function. If x is a function on the path, MATLAB treats x in myfunc as a function and the code runs. Otherwise, MATLAB throws an error.

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

In previous releases, if x was a function on the path, MATLAB treated it as a function in myfunc and as a variable innested. If x was not a function on the path, MATLAB treated it as a variable shared between myfunc andnested. This resulted in code whose output was dependent on the state of the path.

To use an identifier as a variable shared between parent and nested functions, you might need to update your code. For example, you can initialize the identifier to an empty array in the parent function.

Before After
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

Change in precedence of wildcard-based imports

Starting in R2019b, imported functions from wildcard-based imports have lower precedence than variables, nested functions, and local functions. In R2019a and earlier, imports in a function shadowed local functions and nested functions.

For example, in this code, the statement local() calls myfunc/local instead of pkg1.local in the wildcard-based import. The statement nest() calls myfunc/nest instead of pkg1.nest.

Starting in R2019b R2019a and Earlier
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

In the search results for import, look for statements that include the wildcard character (*).

Fully qualified import functions cannot have the same name as nested functions

Starting in R2019b, fully qualified imports that share a name with a nested function in the same scope throw an error.

Starting in R2019b Updated Code R2019a and Earlier
This function errors because it shares a name with a nested function in the same scope.function myfunc import pkg.nest % Errors nest(); function nest end end To call function nest from the import statement, rename local function myfunc/nest.function myfunc import pkg.nest nest(); function newNest end end This function calls function nest from the import statement.function myfunc import pkg.nest nest(); % Calls pkg.nest function nest end end
This function errors because declaring a variable with the same name as the imported function nest is not supported.function myvarfunc import pkg.nest % Errors nest = 1 end Rename variable nest.function myvarfunc import pkg.nest % Errors thisNest = 1 end This function modifies variablenest.function myvarfunc import pkg.nest nest = 1 % Modifies variable nest and % displays warning since R2018a end

Fully qualified imports shadow outer scope definitions of the same name

Starting in R2019b, fully qualified imports always shadow outer scope definitions of the same name. In R2019a and earlier, a fully qualified import was ignored when it shadowed an identifier in the outer scope.

Starting in R2019b Updated Code R2019a and Earlier
Local function nest calls function x from imported package.function myfunc x = 1; function nest % Import function x import pkg1.x % Calls pkg1.x x() end end To use variable x in local function nest, pass the variable as an argument.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 In this code, function nest ignores imported functionx.function myfunc x = 1; function nest % Import function x import pkg1.x % x is a variable x() end end

Error handling when import not found

Starting in R2019b, fully qualified imports that cannot be resolved throw an error with or without Java®. In R2019a and earlier, MATLAB behaved differently depending on whether you started MATLAB with the -nojvm option. Do not use functions like javachk and usejava to customize error messages.

Starting in R2019b Updated Code R2019a and Earlier
This code throws an error when starting MATLAB with the -nojvm option.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 Remove call tousejava.function myfunc import java.lang.String % Errors % Do something with java String class end This code displays a message when starting MATLAB with the -nojvm option.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

Nested functions inherit import statements from parent functions

Starting in R2019b, nested functions inherit import statements from the parent function. In R2019a and earlier, nested functions did not inherit import statements from their parent functions.

Starting in R2019b R2019a and Earlier
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

Change in precedence of compound name resolution

Starting in R2019b, MATLAB resolves compound names differently. A compound name is comprised of several parts joined by a dot (for example, a.b.c), which can be used to reference package members. With R2019b, MATLAB resolves compound names by giving precedence to the longest matching prefix. In previous releases, the precedence order followed a more complex set of rules.

For example, suppose a package pkg contains a classfoo with a static method bar and also a subpackage foo with a function bar.

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

In R2019b, a call to which pkg.foo.bar returns the path to the package function.

Previously, a static method took precedence over a package function in cases where a package and a class had the same name.

Anonymous functions can include resolved and unresolved identifiers

Starting in R2019b, anonymous functions can include both resolved and unresolved identifiers. In previous releases, if any identifiers in an anonymous function were not resolved at creation time, all identifiers in that anonymous function were unresolved.

Starting in R2019b R2019a and Earlier
To evaluate the anonymous function, MATLAB calls the local function lf withx defined in myscript because lf in the anonymous function resolves to the local function.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 considers lf as an unresolved identifier along with x, and usedx to index into the variablelf frommyscript.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

See Also

import

Topics