How to determine if a function was called followed by a semicolon (";")? - matlab

In a Matlab script I call a user-defined function (m-function). My function returns a value while printing the value to the command window using disp and/or fprintf calls.
When writing an expression or a statement, one puts ; at its end to suppress printing. When the expression calls my function, the ; can suppress the printing of the returned value. However, this does not effect the disp output from within the function called.
I want to eliminate the display output of the function when appropriate. Is there a way to determine whether a function call was made in an expression ending with ;?

I like the spirit of what you're trying to do, but I think that it probably goes against the common programming patterns in Matlab. As you correctly state, the purpose of the terminating semicolon is to supress printing of returned values. Trying to get it to incorporate your other feature might well require some deep hacking and ugly hard-to-maintain code. The standard way to implement what you describe is via property name-value pair arguments. For example, Matlab's optimization suite has a property called 'Display' that can be set to various values to indicate the desired level of verbosity (see optimset).
If you want to try looking for a way to check for terminating semicolons, you might look into the undocumented mint, mlintmex, and mtree functions – read more here. Unfortunately, using mlint to simply check for the "Terminate statement with semicolon to suppress output" warning (see this function on the MatlabCental File Exchange) won't work in all cases as a function call by itself doesn't produce this warning.
Update
Here's an attempt at code that could be inserted into a called function to determine if the line of the caller is terminated by a semicolon. You should be aware that this has not been thoroughly tested and is likely very fragile. I have not tested it with sub-functions or anonymous functions and I know that it fails if you wrap a line over multiple lines using ....
st = dbstack('-completenames'); % M-file of caller and line number
caller = st(2);
str = mlint('-lex',caller.file); % Struct containing parsed data
isSemicolon = false; % Assume no semicolon
for i = 1:length(str)
% Find end-of-line corresponding to function call
c = strsplit(str(i).message,'/');
if str2double(c{1}) == caller.line && strcmp(c{2}(end-5:end-1),'<EOL>')
% Check for comments
j = i-1;
if ~isempty(strfind(str(j).message,'%'))
j = j-1;
end
% Check for semicolon
if strcmp(str(j).message(end-2),';')
isSemicolon = true; % Semicolon found
break;
end
end
end
In other words, play around with this to learn, but I would not recommend actually using it.

I'm afraid that the answer to your question is no. That information is simply not passed on to the function being called.
You shouldn't think about adding the semicolon as a means to "suppress printing", but rather that the lack of a semicolon instructs MATLAB to call the display function on the output variables of the function call. In other words, MATLAB interprets this code:
y = myFunc(x)
as:
y = myFunc(x);
display(y);
I think adding a 'print' or 'verbose' parameter to your function is your best bet for achieving what you want.

I think the simplest method to achieve the results you want (i.e. whether or not disp's get displayed) is to add an extra function input or output. For example, adding an input (optional, you can set default behaviour):
function y=myFunc(a,displayResults)
if nargin==1
displayResults=true; %// set the default behaviour
end
%// if you want to print something
if displayResults
disp(a)
end
end
Or an extra output. In this case foo produces no output to the screen, but all the messages are saved into a cell array, which can be accessed if desired:
function [x,m] = foo(a)
m={}; %// initialise cell array of output messages
x=a;
m{length(m)+1}=a; %// some message
m{length(m)+1}='another message'; %// another message
end
I think the first option will be better, the second will not deal with fprintf well, and displaying elements of m could be tricky depending on what it contains. The first method is very simple, and does not even require you to change existing code, as you can make the displayResults input optional and set the default to be what you want.

You may suppress disp outputs by locally redefining it at the beginning of the function:
function [] = hideDisplay()
%[
% Override `disp` behavior
disp = #(x)doNothing;
% Next `disp` calls will no longer appear in matlab console
disp('Hello')
disp('World!')
%]
end
%% ---
function [] = doNothing()
%[
%]
end

Here's a possible workaround (to be clear - this is not a real answer to the question per-se, just a way to avoid the unwanted behaviour). Say my function is:
function y = prt_test(x)
y = x + 1;
disp('IN PRT_TEST')
end
Calling:
>> % Regular use - message and output are displayed:
>> y = prt_test(1)
IN PRT_TEST
y =
2
>> % Regular use w/ ";" - only message is displayed:
>> y = prt_test(2);
IN PRT_TEST
>> % Use "evalc()" - message and output are displayed:
>> evalc('y = prt_test(3)')
ans =
IN PRT_TEST
y =
4
>> % Use "evalc()" w/ func ";" - only message is displayed:
>> evalc('y = prt_test(4);')
ans =
IN PRT_TEST
>> % Use "evalc();" - no output:
>> evalc('y = prt_test(5)');
>> % Use "evalc();" w/ func ";" - no output:
>> evalc('y = prt_test(6);');
>>

Related

What does the code '[~, width ] = size(I);'mean?I can't undestand '~'especially [duplicate]

Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?
Let's say, I have the following function in MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Are there any elegant ways to do this that do work?
So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
I still think this is very ugly code.
With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,
[~, ~, variableThatIWillUse] = myFunction();
Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.
See the release notes for details.
This is somewhat of a hack, but it works:
First a quick example function:
Func3 = #() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)
There's a better approach; see ManWithSleeve's answer instead.
If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.
While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.
I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.
Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(#func)); % For capturing all outputs from "func"
Then call the function as follows:
[a{:}] = func();
Then simply remove the element from a that you want, and overwrite a:
a = a{3}; % Get the third output
I wrote a kth out function:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};
end %function
You can then call
val_i_want = kthout(3, #myfunc, func_input_1, func_input_2);
You could also wrap up the function like:
func_i_want = #(varargin)(kthout(3, #myfunc,varargin{:})); % Assuming you want the third output.
After which you use
val_i_want = func_i_want(func_input_1, func_input_2);
Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.
In MATLAB 2010a, I found a neat way of doing what you are asking for.
It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.
I don't know if this existed in previous versions, but I just came across it recently.
You can make a function (or anonymous function) that only returns selected outputs, e.g.
select = #(a,b) a(b);
Then you can call your function like this:
select(func,2);
select(func,1:3);
Or you can assign the output to a variable:
output(1,2:4) = select(func,1:3);
I don't see any reason not to use ans(n). Like this:
size(rand([5 10 20 40]));
b = ans(2);
It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.
Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:
[~, b] = size(a);
Then b = 8000! (You need to end with ~, to catch more arguments!)

can a matlab function detect if it has been called with semicolon [duplicate]

In a Matlab script I call a user-defined function (m-function). My function returns a value while printing the value to the command window using disp and/or fprintf calls.
When writing an expression or a statement, one puts ; at its end to suppress printing. When the expression calls my function, the ; can suppress the printing of the returned value. However, this does not effect the disp output from within the function called.
I want to eliminate the display output of the function when appropriate. Is there a way to determine whether a function call was made in an expression ending with ;?
I like the spirit of what you're trying to do, but I think that it probably goes against the common programming patterns in Matlab. As you correctly state, the purpose of the terminating semicolon is to supress printing of returned values. Trying to get it to incorporate your other feature might well require some deep hacking and ugly hard-to-maintain code. The standard way to implement what you describe is via property name-value pair arguments. For example, Matlab's optimization suite has a property called 'Display' that can be set to various values to indicate the desired level of verbosity (see optimset).
If you want to try looking for a way to check for terminating semicolons, you might look into the undocumented mint, mlintmex, and mtree functions – read more here. Unfortunately, using mlint to simply check for the "Terminate statement with semicolon to suppress output" warning (see this function on the MatlabCental File Exchange) won't work in all cases as a function call by itself doesn't produce this warning.
Update
Here's an attempt at code that could be inserted into a called function to determine if the line of the caller is terminated by a semicolon. You should be aware that this has not been thoroughly tested and is likely very fragile. I have not tested it with sub-functions or anonymous functions and I know that it fails if you wrap a line over multiple lines using ....
st = dbstack('-completenames'); % M-file of caller and line number
caller = st(2);
str = mlint('-lex',caller.file); % Struct containing parsed data
isSemicolon = false; % Assume no semicolon
for i = 1:length(str)
% Find end-of-line corresponding to function call
c = strsplit(str(i).message,'/');
if str2double(c{1}) == caller.line && strcmp(c{2}(end-5:end-1),'<EOL>')
% Check for comments
j = i-1;
if ~isempty(strfind(str(j).message,'%'))
j = j-1;
end
% Check for semicolon
if strcmp(str(j).message(end-2),';')
isSemicolon = true; % Semicolon found
break;
end
end
end
In other words, play around with this to learn, but I would not recommend actually using it.
I'm afraid that the answer to your question is no. That information is simply not passed on to the function being called.
You shouldn't think about adding the semicolon as a means to "suppress printing", but rather that the lack of a semicolon instructs MATLAB to call the display function on the output variables of the function call. In other words, MATLAB interprets this code:
y = myFunc(x)
as:
y = myFunc(x);
display(y);
I think adding a 'print' or 'verbose' parameter to your function is your best bet for achieving what you want.
I think the simplest method to achieve the results you want (i.e. whether or not disp's get displayed) is to add an extra function input or output. For example, adding an input (optional, you can set default behaviour):
function y=myFunc(a,displayResults)
if nargin==1
displayResults=true; %// set the default behaviour
end
%// if you want to print something
if displayResults
disp(a)
end
end
Or an extra output. In this case foo produces no output to the screen, but all the messages are saved into a cell array, which can be accessed if desired:
function [x,m] = foo(a)
m={}; %// initialise cell array of output messages
x=a;
m{length(m)+1}=a; %// some message
m{length(m)+1}='another message'; %// another message
end
I think the first option will be better, the second will not deal with fprintf well, and displaying elements of m could be tricky depending on what it contains. The first method is very simple, and does not even require you to change existing code, as you can make the displayResults input optional and set the default to be what you want.
You may suppress disp outputs by locally redefining it at the beginning of the function:
function [] = hideDisplay()
%[
% Override `disp` behavior
disp = #(x)doNothing;
% Next `disp` calls will no longer appear in matlab console
disp('Hello')
disp('World!')
%]
end
%% ---
function [] = doNothing()
%[
%]
end
Here's a possible workaround (to be clear - this is not a real answer to the question per-se, just a way to avoid the unwanted behaviour). Say my function is:
function y = prt_test(x)
y = x + 1;
disp('IN PRT_TEST')
end
Calling:
>> % Regular use - message and output are displayed:
>> y = prt_test(1)
IN PRT_TEST
y =
2
>> % Regular use w/ ";" - only message is displayed:
>> y = prt_test(2);
IN PRT_TEST
>> % Use "evalc()" - message and output are displayed:
>> evalc('y = prt_test(3)')
ans =
IN PRT_TEST
y =
4
>> % Use "evalc()" w/ func ";" - only message is displayed:
>> evalc('y = prt_test(4);')
ans =
IN PRT_TEST
>> % Use "evalc();" - no output:
>> evalc('y = prt_test(5)');
>> % Use "evalc();" w/ func ";" - no output:
>> evalc('y = prt_test(6);');
>>

function handles in Octave

I have a question regarding function(handles) in Octave.
So, I want to call a function, which accepts two variables and returns two(the implementation is faulty; but not relevant in this case).
According to the documentation this should be quite straightforward:
function [ret-list] = name (arg-list)
body
endfunction
I'm trying the following:
function two_d_comp = twodcomp
twodcomp.twoDperp=#perp;
^
end
function twoDperp[vmag, vangle]=perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end;
I saved the function in a file called twodcomp.m.
When I call the function as follows:
[X, Y] = twodcomp.twoDperp(1,2)
Octave spits out the following:
error: #perp: no function and no method found
error: called from
twodcomp at line 2 column 20
I managed to remove the error by removing the output arguments vmag and vangle, as follows:
function twoDperp=perp(x,y)
But this is obviously not really what I want.
Do you guys happen to have some pointers as to what I'm doing wrong?
Cheers
Your initial function twodcomp: you cannot have the output variable (before the =) be named the same as your function name (after the =).
Then if you want to assign an anonymous function (MATLAB docs, Octave docs) using the # notation, you can still pass the desired inputs.
So rewrite it like:
% Include empty parentheses after a function name to make it clear which is the output
function output = twodcomp()
% Not sure why you're assigning this function to a struct, but
% still give yourself the ability to pass arguments.
% I'm assuming you want to use the output variable,
% and not reuse the main function name (again)
output.twoDperp = #(x,y) perp(x,y);
end
With your second function, you just need to remove the twoDperp before your output arguments. In your question you state the expected syntax from the docs, but then didn't follow it...
function [vmag, vangle] = perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end
Now these can be used like so:
% Deliberately using different variable names to make it clear where things
% overlap from the function output. twodcomp output is some struct.
myStruct = twodcomp();
% The output struct has the field "twoDperp" which is a function with 2 outputs
[m, a] = myStruct.twoDperp(1,2);

How does function work regarding to the memory usage?

When you are using function in MATLAB you have just the output of the function in the work space and all the other variables that maybe created or used in the body of that function are not shown. I am wondering how does function work? Does it clear all other variables from memory and just save the output?
function acts like a small, isolated programming environment. At the front end you insert your input (e.g. variables, strings, name-value pairs etc). After the function has finished, only the output is available, discarding all temporarily created variables.
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
end
>> A=1:10
>> MySum(A)
This code just adds two consecutive values for the input array A. Note that the iteration number, stored in kk, is not output and is thus discarded after the function has completed. In MATLAB kk(ii) = ii; will be underlined orange, since it 'might be unused'.
Say you want to also retain kk, just add it to the function outputs:
function [SUM,kk] = MySum(A)
and keep the rest the same.
If you have large variables that you only use up to a certain point and wish them not clogging up your memory whilst the function is running, use clear for that:
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
clear kk
end

How to elegantly ignore some return values of a MATLAB function

Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?
Let's say, I have the following function in MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Are there any elegant ways to do this that do work?
So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
I still think this is very ugly code.
With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,
[~, ~, variableThatIWillUse] = myFunction();
Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.
See the release notes for details.
This is somewhat of a hack, but it works:
First a quick example function:
Func3 = #() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)
There's a better approach; see ManWithSleeve's answer instead.
If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.
While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.
I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.
Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(#func)); % For capturing all outputs from "func"
Then call the function as follows:
[a{:}] = func();
Then simply remove the element from a that you want, and overwrite a:
a = a{3}; % Get the third output
I wrote a kth out function:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};
end %function
You can then call
val_i_want = kthout(3, #myfunc, func_input_1, func_input_2);
You could also wrap up the function like:
func_i_want = #(varargin)(kthout(3, #myfunc,varargin{:})); % Assuming you want the third output.
After which you use
val_i_want = func_i_want(func_input_1, func_input_2);
Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.
In MATLAB 2010a, I found a neat way of doing what you are asking for.
It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.
I don't know if this existed in previous versions, but I just came across it recently.
You can make a function (or anonymous function) that only returns selected outputs, e.g.
select = #(a,b) a(b);
Then you can call your function like this:
select(func,2);
select(func,1:3);
Or you can assign the output to a variable:
output(1,2:4) = select(func,1:3);
I don't see any reason not to use ans(n). Like this:
size(rand([5 10 20 40]));
b = ans(2);
It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.
Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:
[~, b] = size(a);
Then b = 8000! (You need to end with ~, to catch more arguments!)