简体   繁体   中英

define anonymous function as 2 of 4 outputs of m file function

I have an m-file function with 4 outputs. I would like to define an anonymous function that has the same inputs, but only produces 2 of the four outputs. Is this possible?

AFAIK, you can't do this with just an inline anonymous function, because that Matlab syntax doesn't provide a way of capturing and indexing in to multiple outputs of a function in a single expression. But you can write a couple reusable helper functions that do so, and then define anonymous functions using them.

Let's say your four argout function is named "f4".

function varargout = f4(x)
%F4 Dummy function that returns 4 argouts holding identifying indexes
varargout = num2cell(1:4);

Here's a reusable helper function that remaps outputs of a function call.

function varargout = callandmap(fcn, ix, varargin)
%CALLANDMAP Call a function and rearrange its output arguments

tmp = cell(1,max(ix));        % Capture up to the last argout used
[tmp{:}] = fcn(varargin{:});  % Call the original function
varargout = tmp(ix);          % Remap the outputs

Now you can make anonymous, argout-remapping functions like this. Here, g holds an anonymous function that takes the same inputs as your original function, but just returns 2 of its original 4 outputs.

>> g = @(varargin) callandmap(@f4, [2 4], varargin{:})
g = 
    @(varargin)callandmap(@f4,[2,4],varargin{:})
>> [a,b] = g('dummy') % gets argouts 2 and 4 from original f4() function
a =
     2
b =
     4
>> 

Using varargin allows you to omit trailing arguments when the resulting function handle is called. If you know all argins will always be provided, you can use named argins for readability if you want.

You can get even fancier and do this with a closure.

function fcn = mapargout(fcnIn, ixArgout)
%MAPARGOUT Create wrapper function that selects or reorders argouts
%
% fcn = argoutselector(fcnIn, ixArgout)
%
% Wraps a given function handle in a function that rearranges its argouts.
% This uses closures so it may have performance impacts.
%
% FcnIn is a function handle to wrap.
%
% IxArgout is a list of indexes in to the original functions argout list
% that should be used as the outputs of the new function.
% 
% Returns a function handle to a new function.

fcn = @extractor;

    function varargout = extractor(varargin)
    n = max(ixArgout);
    tmp = cell(1,n);
    % Call the wrapped function, capturing all the original argouts
    [tmp{:}] = fcnIn(varargin{:});
    % And then select the ones you want
    varargout = tmp(ixArgout);
    end

end

This results in simpler code for creating the anonymous function. And you could compose it with other function wrapper calls.

>> g = mapargout(@f4, [2 4])
g = 
    @mapargout/extractor
>> [a,b] = g('dummy')
a =
     2
b =
     4
>> 

But closures can be tricky to work with in Matlab and may have performance implications. The callandmap approach is probably preferable unless you need the extra power.

If the two outputs are #1 and #2, everything is fine, and you don't have to worry about the other two outputs.

If the two outputs are any two others, you have two options

(1) Create a wrapper function with two outputs (note that in newer versions of Matlab you can replace the unused outputs dummy by ~ .

function [out1,out2] = wrapperFunction(in1,in2,in3)
   [dummy,out1,dummy,out2] = mainFunction(in1,in2,in3);

(2) Add another input variable that allows you to switch your function's behavior

function varargout = mainFunction(in1,in2,in3,outputSwitch)
   %# make output switch optional
   if nargin < 4 || isempty(outputSwitch)
      outputSwitch = 0;
   end

   %# calculation here that creates out1-4

   if outputSwitch
       %# the special case where we only want outputs 2 and 4
       varargout = {out2,out4};
   else
       %# return all four outputs
       varargout = {out1,out2,out3,out4}
   end

Then you can create the anonymous function as usual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM