Why am I warned about defining variables in a nested function, when I don't?

조회 수: 6 (최근 30일)
  1. EDIT: The following is an newer and simpler description of the problem:
Every time I run my function warnTest(), I receive a warning about defining the variable "ind" in the nested function. But I don't define the variable "ind" in the nested function. The warning doesn't seem to be true.
Furthermore, why am I not warned about the variable "n", which is also defined in the parent function and shared with the nested function, just like the variable "ind"?
function warnTest()
% % warnTest() reproduces the following warnings:
%
% Warning: File: /path/to/warnTest.m Line: 27 Column: 29
% Defining "ind" in the nested function shares it with the parent function. In a future release, to share "ind" between parent and nested functions, explicitly define it in the parent function.
% Warning: File: /path/to/warnTest.m Line: 27 Column: 42
% Defining "ind" in the nested function shares it with the parent function. In a future release, to share "ind" between parent and nested functions, explicitly define it in the parent function.
%
% However, warnTest() doesn't define the variable "ind" in the nested
% function, as suggested by the warning message.
%
% Additionally, warnTest() also defines the variable "n" in the parent
% function and shares it with its nested function. However, MATLAB issues
% no warning about the variable "n".
%
% This behaviour has been observed in the following MATLAB Releases:
%
% MATLAB® R2018a Update 6 (9.4.0.949201) 64-bit (maci64) September 5, 2018
% MATLAB® Version: 9.6.0.1150989 (R2019a) Update 4 64-bit Windows 10
% Define labels for divisor and dividend
f = ["a","a","a","a","a","b","b","b","b","b"];
l = numel(f);
k = unique(f);
n = numel(k);
m = 7;
p = 5;
% Define divisor and dividend
A = randi(100,m,l);
B = randi(100,p,l);
% Define var ind in parent function
for ii = n:-1:1
ind{ii} = find(k(ii) ~= f);
end
C = nestFun(A,B);
disp(C);
% Define nested function
function [Z] = nestFun(X,Y)
for jj = n:-1:1
Z(:,:,jj) = X(:,ind{jj})/Y(:,ind{jj});
end
end
end
  1. EDIT: The following is an older, slightly more complicated description of the problem:
Every time I run my parentFunction.m, I receive 2 warnings like the following:
Warning: File: /path/to/my/parentFunction.m Line: 439 Column: 34
Defining "train_ind" in the nested function shares it with the parent function. In a future release, to share "train_ind" between parent and nested functions, explicitly define it in the
parent function.
> In callerFunction (line 76)
Warning: File: /path/to/my/parentFunction.m Line: 439 Column: 59
Defining "train_ind" in the nested function shares it with the parent function. In a future release, to share "train_ind" between parent and nested functions, explicitly define it in the
parent function.
> In callerFunction (line 76)
However, the variable "train_ind" is explicitly defined in the parent function, before the nested function is first called.
So, why would I receive that warning, if it doesn't apply to my function?
(Then again, the warning is thrown in the callerFunction, in the line 76 which calls the parentFunction.m. Should that make a difference?)
My release: MATLAB® R2018a Update 6 (9.4.0.949201) 64-bit (maci64) September 5, 2018
The parentFunction.m is fairly long, so I'll show you the relevant lines only.
  • In line 241 I first define the variable in question:
% Build training & testing index for cross-validation
for ii = n_folds:-1:1
train_ind{ii} = find(k(ii) ~= folds);
test_ind{ii} = find(k(ii) == folds);
end
  • In line 256 I first call the nested function:
% Train encoding model for the entire brain
weights(:,:,:,ff) = IEM_train(betas, des(:,:,ff));
  • In line 429 I define the nested function:
function [weights] = IEM_train(betas, des_mat)
% Train encoding model with cross-validation
% Initialise weights
weights = NaN(n_vert,n_chans,n_folds);
% Loop over cross-validation folds
for nn = n_folds:-1:1
% Compute weights for each fold
weights(:,:,nn) = betas(mask,train_ind{nn})/des_mat(:,train_ind{nn});
end
end
  댓글 수: 6
JMM
JMM 2020년 9월 23일
@John D'Errico My release: MATLAB® R2018a Update 6 (9.4.0.949201) 64-bit (maci64) September 5, 2018
Rik
Rik 2020년 9월 24일
My copy (R2020a_u5 on W10) doesn't return any warning (mlint or otherwise) when running your example function.

댓글을 달려면 로그인하십시오.

채택된 답변

Andreas Apostolatos
Andreas Apostolatos 2020년 9월 25일
편집: Andreas Apostolatos 2020년 9월 26일
Hello everyone,
It appears so, that this warning does not persist for release R2019b and later releases when cell array 'ind' is implicitly initialized as in the provided code.
The trigger of this warning in the prior to R2019b releases seems to be the fact that cell array 'ind' is not explicitly initialized in the parent function.
By explicitly initializing array 'ind' before the loop where its elements are being assigned in the parent function, namely,
ind = cell(n, 1);
for ii = n:-1:1
ind{ii} = find(k(ii) ~= f);
end
the warning disappears also in the releases prior to R2019b.
Best Regards,
Andreas
  댓글 수: 3
John D'Errico
John D'Errico 2020년 9월 26일
This now makes sense. Many thumbs up to Andreas for explaining this. The simple answer is thus to upgrade MATLAB, but the other takeaway is to always preallocate grown arrays. And we should be doing that anyway.
Andreas Apostolatos
Andreas Apostolatos 2020년 9월 26일
Thanks a lot John, I am happy I could help.

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Bjorn Gustavsson
Bjorn Gustavsson 2020년 9월 23일
Because nested functions share the name-space with its parrent function. That is all variables in the parrent function are available in the nested function - pretty much as global variables. Apparently variables defined in a nested function also become available in its parrent function.
(There might be good use-cases for nested functions, but the "global" nature (between parrent and nested function) of the variables made me stay away from nested functions - it is, in my experience, possible to get by with sub-functions in all cases. The global-nature will obvoiusly come with similar problems as global variables in general - they might randomly change variables rather far away from where the problems arise, which makes debugging challenging. It took me some 15-20 years to weed out global variables from a toolbox I started with before I learnt how much problems they might cause. To be fair for the nested functions the problem is way more contained than for global variables in general. But, again "in my opinion", the problem is of the same character, and you have at least a 400-lines file. I guess the warning is there to tell you what will/might happen in future releases. I'd switch to a subfunction - but you might very well have good reasons for using a nested function...)
HTH
  댓글 수: 10
JMM
JMM 2020년 9월 23일
I have adapted the title of my question to reflect the oddity, that MATLAB sends me a warning about something which does not seem to be the case.
Bjorn Gustavsson
Bjorn Gustavsson 2020년 9월 23일
@Stephen: and it seems to vary a bit between versions, in my first version the variable x deeper in limbo than a variable specified with persistent that's not been assigned to anything...
@JMM: for that use I stick to sub-functions and bear the burden of the longer argument-lists - and have the relief to know that I don't have to worry about peculiar side-effects of my functions (and with matlabs call-by-reference-until-modified I'm under the impression that there is not much additional overhead.)

댓글을 달려면 로그인하십시오.


Stephen23
Stephen23 2020년 9월 23일
편집: Stephen23 2020년 9월 23일
So far no one has actually explained the warning, which is a pity because this is really quite an interesting question.
Some answers/comments have explained the basic concept of nested functions (Surprise! Nested functions can share variables between workspaces!), but so far no one has actually put forward a plausible explanation of this warning in the context given in the question.
Here are a few possible explanations of this strange warning:
  • Some version-specific warning. Perhaps it was decided to remove this (rather superfluous?) warning, so it only appeared in one/a few releases.
  • Some special syntax that confuses the mlint parser, so that it cannot recognize that the variable is also defined in the parent workspace. For example, does the code include any (awful, anti-pattern) magic like eval, assignin, or any debugging commands? Does the code use cells or anything similar? Is it written in a script?
  • Is the variable name also the name of a function? Check using which.
  • Spelling. Yes, really. For example, it is very easy to miss a different character case: is it really x defined in the parent workspace, or is it X ? You can use the syntax highlighting to help check this: https://www.mathworks.com/help/matlab/matlab_prog/check-variable-scope-in-editor.html
If you want more help on this please tell us the exact MATLAB release you are using and upload the code.
EDIT: as little bit of internet searching found this, which might be related:
https://www.mathworks.com/help/matlab/release-notes-R2017b.html -> Language and Programming -> Functionality being removed or changed -> "Sharing uninitialized variables between a nested function and the parent function"
  댓글 수: 7
JMM
JMM 2020년 9월 24일
편집: JMM 2020년 9월 24일
@Stephen Cobeldick: I wrote a simpler function which reproduces my problem on two different installations & systems. I have added it to the top of my question. It doesn't seem to be related to eval(), assignin(), debugging settings, or code sections. I have also submitted a bug report to Mathworks.
Stephen23
Stephen23 2020년 9월 24일
@JMM: good work on eliminating those possibilities. So far it really does seem that a (recently introduced) warning is either a) worded incorrectly and needs to be re-written, or b) is being shown as a result of a false-positive match by the mlint parser. I tried your example on earlier versions of MATLAB, with no warning.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by