Home > Back-end >  'too many output arguments' error when passing function to another function in Matlab
'too many output arguments' error when passing function to another function in Matlab

Time:03-17

I have some error handling code that I want a bunch of functions to use, so in order to avoid repetition I thought I would put it in my generic class that holds utility functions FunctionContainer.

Here's a truncated version of FunctionContainer:

classdef FunctionContainer
methods (Static)
    
    function run(func, ExpInfo, logdir, newdir, varargin)
        try 
            func(ExpInfo, newdir, varargin)
        catch ME
            FunctionContainer.errproc(logdir, newdir, ME)
        end
    end
    
    function errproc(logdir, newLogDir, ME) 
        errdir = fullfile(logdir, 'error');
        movefile(newLogDir, errdir);
        pathParts = strsplit(newLogDir, filesep);
        logID = pathParts(end);
        newLogText = fullfile(errdir, logID, 'error.txt');
        fid = fopen(newLogText, 'wt');
        fprintf(fid, '%s\n%s\n', ME.identifier, ME.message);
        for i = 1:length(ME.stack)
            fprintf(fid, '%i\t%s\n', ME.stack(i).line, ...
                ME.stack(i).file);
        end
        fclose(fid);
        rethrow(ME);
    end
  
    function newdir = prolog(logdir, id, supfiles)
        id = join([id, string(clock)], '_');
        newdir = fullfile(logdir, id); mkdir(newdir)
        stack = dbstack('-completenames');
        files = horzcat({stack.file}, supfiles);
        for i = 1:numel(files)
            copyfile(files{i}, newdir)
        end    
    end
end

end

Here's the context in which I'm using it:

function realign(ExpInfo)

    fc = FunctionContainer;
    logdir = ExpInfo.logdir;
    ws = fullfile(logdir, 'workspace.mat'); save(ws);
    newdir = fc.prolog(logdir, 'realign', {ws});

    fc.run(runRealign, ExpInfo, logdir, newdir);

    function runRealign(ExpInfo, newdir)
         % do a bunch of stuff
    end
end

The relevant line in my script ks_main.m that calls realign is

realign(FullData)

I get this error:

8   fc.run(runRealign, ExpInfo, logdir, newdir);
Error using realign/runRealign
Too many output arguments.

Error in realign (line 8)
fc.run(runRealign, ExpInfo, logdir, newdir);

Error in ks_main (line 35)
realign(FullData)

I just don't understand this error in this context. None of these functions is returning anything or has any outputs. I could maybe understand if runRealign were getting too many inputs, and I tried defining runRealign like this

function runRealign(ExpInfo, newdir, varargin)

but that made no difference. Maybe this has something to do with passing a function as an argument to another function? What's the right way to do this in Matlab?

CodePudding user response:

You need to put the @ symbol in front of your function argument in fc.run. Always do this when passing a function handle as an argument (https://au.mathworks.com/help/matlab/matlab_prog/pass-a-function-to-another-function.html). Line 8 of realing.m should be:

fc.run(@runRealign, ExpInfo, logdir, newdir);

There are a couple of other issues. One is that you are missing an end at the end of FunctionContainer. This is probably just a typo in your question or else you would also have an error related to this.

Another small implementation detail is that you don't need to use logdir as an argument if it is going to be a field in ExpInfo anyway---you can simply access it from ExpInfo inside of FunctionContainer without having to pass it explicitly to run. Passing both ExpInfo and its field logdir to the same function is unclear and stylistically bad practice. (Which reminds me, you should provide a definition of FullData in your question as well. I had to discern that it requires this field.)

However, this is code as is is also going to cause an exception to be thrown on line 6 of FunctionContainer. The definition of runRealign only takes 2 arguments, but when you try to run it in FunctionContainer you expect 3: func(ExpInfo, newdir, varargin). If I change line 6 of FunctionContainer to:

func(ExpInfo, newdir)

it works.

To make this robust and error free you need either to parse the varargin in FunctionContainer so that it intelligently handles a variable number of arguments (https://au.mathworks.com/help/matlab/ref/varargin.html), or else guarantee that the input function handle points to one that has 2 arguments for ever and always.

  • Related