Matlab is confused between line (function) and line (variable)

14 views (last 30 days)
see code: In a certain power system simulation, I am naming my outputs (typically more than one, a linear MIMO simulation) in the following way.
Nameyout=[repmat('Real power flow between lines ,length(OutputChannels),1) num2str(reshape(line(OutputChannels,1), [],1)) repmat(' and ', length(OutputChannels),1) num2str(reshape(line(OutputChannels,2),[],1))];
Nameyout = [Nameyout repmat(' (MW)', length(OutputChannels),1)];
assuming following values for my variables
OutputChannels = 1;
line = [5 21];
I would except the Nameyout to be
Real power flow between lines 5 and 21 (MW)
but I am getting this value
Real power flow between lines 0.0048828 and 173.0049 (MW)
And a figure window appears. I suspect that the
line(X,Y)
function is being called by the Matlab run-time and the variable in the function workspace is being neglected. However, there is no warning. Just to be sure that I am doing everything right, I executed the line on a break-point.
Another funny thing happens is that if I put a break-point at this particular line in the function and select-execute the line, everything works as expected. However, when I run the function, it returns an invalid answer. I guess a way to deal with this is to rename my variable
line
something else. And it seems to me that this is more of a glitch in how Matlab run-time identifies and dispatches on whether a given symbol is a variable, a function or some-other construct.
Having described my situation and problem, I am not sure if I am asking a question or just pointing out a situation I encountered today. If I am to ask a question, that would - How do I make sure that Matlab run-time dispatches the right variable versus the built-in function. Is there any priority and how is it decided? How could I do this differently and not find myself in such an issue.
FYI: I did try to put the above in a loop with same result.

Answers (4)

Jan
Jan on 13 Jun 2011
Simple advice, which has been given in this and other forums every week:
Do not use names of built-in or toolbox functions as names of a variable.
  6 Comments
Jan
Jan on 14 Jun 2011
@Gurudatha: EVAL('line') is simply cruel.
Actually Matlab interpretes the amgiguous usage of equal names for functions and variables unequivocally as an error:
function myTest
line(1:10, 1:10);
line = 5; % ERROR!
But Matlab has no chance to detect this error reliably, if the variable is created dynamically by EVAL or the function call is concealed in a potentially evaluated subsection:
function myUglyTest
if rand < 0.5, line(1:10, 1:10); end
line = 5;
Brrrrrr. Of course this is processed by Matlab in a strictly defined way and we are able to write the applied rules down here explicitely. But at least any user who is reading the code in the future will be confused. And the degree of confusion makes the bug worse than a simple typo - it is an evil bug!
I dare to bet that the top 20 repliers of MATLAB Answers cannot forecast the behaviour of this reliably:
function myBruteTest
eval('line = [5,6]');
line(1,2); % ??? What will happen?
eval('line(1,2)'); % ??? Function or variable?
My conclusion: You are right - there is no really practical method to rename the variables. If I had to work with such a program, I would *delete it* and reprogram it from scratch using a reliable naming scheme. There is simply no trustworthy way to run a program which is based on questionable symbols. You are working with a junk program. Sorry for this not (or non-?) constructive comment. Junk programs produce junk results. And from a scientic point of view, junk results are *no* results.
Kelly Kearney
Kelly Kearney on 14 Jun 2011
Jan, I disagree that using a variable name that conflicts with a function name is necessarily "bad programming." Particularly in Matlab, where there are so many functions that one is bound to accidentally come in conflict with one of them eventually. The solution is simply to make sure you use good programming practice and "declare" all your variables in some way, rather than magicking them into your workspace via load, eval, etc. Of course, avoiding function names that make convenient variable names but are also very commonly-used functions (plot, line, min, max, diff, etc) is advisable so you can still use those functions later in the code. But in this case, where the code is legacy and rewriting would be more trouble than it's worth, then a simple explicit definition of the variable should prevent any problems.

Sign in to comment.


Walter Roberson
Walter Roberson on 14 Jun 2011
If you know you are going to be loading a variable named "line", then you can avoid confusing the JIT by initializing "line" as a variable before you do the load().
For example,
line = [];
load('xyz.mat');
MATLAB's JIT would see the initialization of "line" and would know that after that, "line" is to be a variable and not a function.

Matt Fig
Matt Fig on 13 Jun 2011
In addition to Jan's sage advice, you misplaced an apostrophe:
OutputChannels = 1;
line = [5 21];
Nameyout=[repmat('Real power flow between lines ',length(OutputChannels),1) num2str(reshape(line(OutputChannels,1), [],1)) repmat(' and ', length(OutputChannels),1) num2str(reshape(line(OutputChannels,2),[],1))];
Nameyout = [Nameyout repmat(' (MW)', length(OutputChannels),1)]
I believe there must be a more elegant way of doing what you are doing, but since I only have the one example I don't know how to get there. For example, is OutputChannels sometimes greater than 1? If so, what do you expect the results to look like?
If you are stuck with the name line because of legacy code, you can still acces the built-in by calling the function BUILTIN.
help builtin
  3 Comments
Matt Fig
Matt Fig on 13 Jun 2011
But what I pasted returns:
Real power flow between lines 5 and 21 (MW)
Gurudatha Pai
Gurudatha Pai on 14 Jun 2011
Yes, it does if you run correctly at the command prompt. The code snippet I have put in here is inside a function and the function loads a .mat file which defines the variable 'line'. The variable 'OutputChannels' can be more than one in length and it is passed as an input argument to this function.
In reality 'line' is a 45x54 matrix which defines various properties of a power system. So, when 'OutputChannels' is greater than one in length I would expect an output like,
Real power flow between lines 5 and 21 (MW)
Real power flow between lines 5 and 22 (MW)
which is a matrix with same number of rows as 'OutputChannels' and describes the various outputs of this function qualitatively.

Sign in to comment.


Kelly Kearney
Kelly Kearney on 13 Jun 2011
Are you sure you've defined the line variable prior to your Nameyout definition? And are you defining it as above, or poofing it into your workspace somehow (via a load command, or eval, or something of the sort)?
If the latter, that will cause problems, since the function will make decisions prior to running about whether each name refers to a variable or a function.
I only get the errant figure and line handle behavior you describe if I fail to define the variable at all, or magic it into the function workspace via load. If line is indeed defined as you describe it, it works fine (well, once I fixed the missing quote).
  2 Comments
Gurudatha Pai
Gurudatha Pai on 13 Jun 2011
I did load the variables inside the function and that happens to be the 10th executable line in the file and this code fragment that I have mentioned above is way down, may be 100+th executable code line.
Besides, As I mentioned above, if I stopped the execution at this line with a break-point, select the above code fragment and run it (at the Matlab command prompt or by hitting F9), it would run just fine.
Some other details: Nameyout is an output argument. So, in reply to your comment, I am not sure if that would classify as defining the variable 'line' prior to the definition of 'Nameyout'!
Kelly Kearney
Kelly Kearney on 14 Jun 2011
In this case, no, you did not explicitly define "line". And Walter's suggestion will solve the problem. The difference between running at the command line, or stopping the function in the debugger and then running that single line, is that functions are preparsed before they are run, while command line commands are not. In other words, Matlab decides, prior to running any lines of function code, which words in your code are defined as variables, and which are functions. In your case, when it scans your code, it has no way of knowing that a variable named line will appear as the result of your load command, but it does know that line is an existing function, so it assigns all appearances of "line" to that function. If you had a little statement like
line = [];
load('xyz.mat');
or
A = load('xyz.mat');
line = A.line;
then Matlab will know in advance that there will be a variable named line and everything will work fine.

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!