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 |