Equivalent of inputname() for output variables

조회 수: 33(최근 30일)
Oliver Woodford
Oliver Woodford 2014년 7월 21일
답변: Matt J 2022년 12월 1일
Say I have a function:
function B = myfun(A)
disp(inputname(1))
disp(outputname(1))
B = A;
If I call it from the command line as follows:
C = 1;
D = myfun(C)
I get:
C
Undefined function 'outputname' for input arguments of type 'double'.
Error in myfun (line 3)
disp(outputname(1))
That's because, unlike inputname(), which returns the name of the input variables in the caller workspace, an equivalent function for output variable names, outputname(), does not exist. My question is, is there any way of getting the names of output variables in the caller workspace?
  댓글 수: 6

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

채택된 답변

Jan
Jan 2015년 4월 16일
편집: Jan 2015년 4월 16일
You can do this by obtaining the caller tree by dbstack and parse the corresponding line of the calling M-file.
But I strongly recommend not to do this. The processing should not be based on the names of variables, because varaibales belong to the program, while the program should operate on the data. So mixing the program's source code with the operations on the data is a anti-pattern for clean programming. Such meta-programming increases the complexity of code dramatically. It is the opposite of the information-hiding principle in the object oriented programming. So even inputname is a strange command from this point of view.
Remember that such methods must fail, when the code is compiled.
When the names of the variables really matter, it would be a clean way to program this explicitly:
Data.A = 1:5;
Data.ReturnVariable = 'B';
Data = myfun(Data);
function Data = myfun(Data);
Data.(Data.ReturnVariable) = Data.A;
This is a little bit longer, but it is clean and clear. You cannot get obstacles like anonymous variables, as calls like this would cause with outputname:
B{3} = myfun(A);
or:
field = 'asd';
S.(field) = myfun(A);
  댓글 수: 4
Matt J
Matt J 2022년 11월 30일
편집: Matt J 2022년 12월 1일
You can do this by obtaining the caller tree by dbstack and parse the corresponding line of the calling M-file.
Unfortunately, that won't work if there is no calling mfile, i.e., if the function is invoked from the command line (though potentially you could parse History.xml).
It also won't work when the call is made using a function handle.
fhandle=@Func;
[A,B]=fhandle(); C=sin(pi) %(*)
function varargout=Func
varargout={1,2};
s=dbstack('-completenames');
currentFunction=s(1).name
end
In the example above, the command s=dbstack('-completenames') produces information that Func() is executing, but no information about which of the commands in line (*) has invoked it,
currentFunction =
'Func'

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

추가 답변(1개)

Matt J
Matt J 2022년 12월 1일
I've implemented Jan's idea in this FEX submission,
but it has some caveats (see below)
>> [A, ~, C]=func()
A =
'a'
C =
'c'
function varargout=func()
varargout=lower(outputnames);
end
The caveats are,
1. The line of code or the command line where the function call is
made must contain no other commands. The above example would fail,
had we done,
[A,B]=func(); [C,D]=func()
2. Function calls where the outputs contain indexing expressions
will have unjpredicatable behavior, e.g.,
[A{1,2}]=func()

Community Treasure Hunt

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

Start Hunting!

Translated by