Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ;?

like image 565
ysap Avatar asked Nov 20 '14 20:11

ysap


2 Answers

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.

like image 112
horchler Avatar answered Sep 26 '22 14:09

horchler


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.

like image 26
KQS Avatar answered Sep 24 '22 14:09

KQS