Можно ли получить возвращаемое значение "nth" из функции без необходимости создавать фиктивные переменные для всех возвращаемых значений n-1
до этого?
Скажем, у меня есть следующая функция в MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Теперь предположим, меня интересует только третье возвращаемое значение. Это можно сделать, создав одну фиктивную переменную:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
Но я думаю, что это отвратительно. Я бы подумал, что вы могли бы сделать что-то вроде одной из следующих вещей, но вы не можете:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Есть ли какие-нибудь изящные способы сделать это, чтобы они работали?
До сих пор лучшим решением было просто использовать variableThatIWillUse
как фиктивную переменную. Это избавляет меня от необходимости создавать реальную фиктивную переменную, которая загрязняет рабочее пространство (или что мне нужно будет очистить). Короче: решение состоит в том, чтобы использовать variableThatIWillUse
для каждого возвращаемого значения до интересующего. Возвращаемые значения можно просто игнорировать:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
Я все еще думаю, что это очень уродливый код, но если нет лучшего способа, я думаю, что я приму ответ.
Это несколько хак, но он работает:
Сначала быстрая функция примера:
Func3 = @() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Теперь ключевым моментом является то, что если вы используете переменную дважды в левой части назначения с несколькими выражениями, более раннее назначение сбрасывается более поздним назначением:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(отредактируйте: просто чтобы проверить, я также проверил, что этот метод работает с [mu,mu,mu]=polyfit(x,y,n)
, если все, о чем вы заботитесь из polyfit
, является третьим аргументом)
изменить: есть лучший подход; см. ManWithSleeve.
В MATLAB версии 7.9 (R2009b) вы можете использовать ~, например,
[~, ~, variableThatIWillUse] = myFunction();
Обратите внимание, что ,
не является необязательным. Просто набрав [~ ~ var]
, он не будет работать и выдает ошибку.
Подробнее см. примечания к выпуску.
not
как don't care
, тоже не так уж плохо
Если вы хотите использовать стиль, в котором переменная будет оставлена, чтобы упасть в ведро бит, разумной альтернативой является
[ans,ans,variableThatIWillUse] = myfun(inputs);
ans - это, конечно, стандартная мусорная переменная для matlab, которая часто перезаписывается в ходе сеанса.
В то время как мне нравится новый трюк, который MATLAB теперь разрешает, используя символ ~ для обозначения игнорируемой возвращаемой переменной, это проблема для обратной совместимости, поскольку пользователи более старых версий не смогут использовать ваш код. Обычно я избегаю использовать такие новые вещи, пока не выпустят хотя бы несколько выпусков MATLAB, чтобы обеспечить очень мало пользователей, оставшихся в беде. Например, даже сейчас я нахожу, что люди все еще используют достаточно старый выпуск MATLAB, который не может использовать анонимные функции.
Вот еще один вариант, который вы можете использовать. Сначала сделайте массив ячеек для захвата всех выходов (вы можете использовать функцию NARGOUT, чтобы определить, сколько выходов возвращает данная функция):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(@func)); % For capturing all outputs from "func"
Затем вызовите функцию следующим образом:
[a{:}] = func();
Затем просто удалите элемент из a, который вы хотите, и перезапишите a:
a = a{3}; % Get the third output
Я написал функцию kth out:
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;
% global:
% nb:
% See also:
% todo:
% changelog:
%
%% %UNFOLD
[outargs{1:k}] = feval(ffnc,varargin{:});
kth = outargs{k};
end %function
вы можете вызвать
val_i_want = kthout(3,@myfunc,func_input_1,func_input_2); %etc
вы также можете завершить функцию, например
func_i_want = @(varargin)(kthout(3,@myfunc,varargin{:})); %assuming you want the 3rd output.
после которого вы используете
val_i_want = func_i_want(func_input_1,func_input_2);
Обратите внимание, что есть служебные данные, связанные с использованием анонимных функций, подобных этому, и это не то, что я сделал бы в коде, который будет называться тысячи раз.
В Matlab 2010a я нашел аккуратный способ делать то, о чем вы просите. Это просто использовать characher "~" (без кавычек, конечно) в качестве вашей фиктивной переменной (столько, сколько вы хотите, возвращая несколько параметров). Это также работает для входных параметров для функций, если функции предназначены для обработки отсутствующих данных. Я не знаю, существовало ли это в предыдущих версиях, но я недавно наткнулся на него.
Вы можете создать функцию (или анонимную функцию), которая возвращает только выбранные выходы, например
select = @(a,b) a(b);
Затем вы можете вызвать свою функцию следующим образом:
select(func,2);
select(func,1:3);
Или вы можете назначить вывод переменной:
output(1,2:4) = select(func,1:3);
decimatedfftx = select(fft(x,12),1:4:12);
select(func,2)
вызывает func(2)
. Я не вижу, где это выбирает выходные аргументы.
Есть ли причина не использовать ans (n), например:
a=rand([5 10 20 40]);
size(a);
b=ans(2);
Дает b = 10, и будет ли этот способ не совместим со всеми версиями Matlab?
Кроме того, это работает, чтобы получить второй выходной аргумент, когда вы не знаете, сколько аргументов будет! Если вы это сделаете:
[~, b] = size(a);
Тогда b = 8000! (Вам нужно закончить с ~, чтобы уловить больше аргументов!)
size(a)
и [b,c]=size(a)
возвращают разные вещи. Функции в MATLAB изменяют поведение в зависимости от количества выходных аргументов.
Я обнаружил, что если вам нужен только один вывод, вы можете пересечь функцию с матрицей единиц измерения, соответствующую желаемому выходу. т.е. out_arg_the_third = функция (input_args) * [0; 0; 1; 0];
или усложняясь, вы можете расширить размеры своей матрицы, чтобы собрать больше результатов: out_arg_second_and_third = функция (input_args) * [0,0; 1,0; 0,1; 0,0]; но мы начинаем терять элегантность здесь.
Должны быть лучшие способы с более новыми версиями, но по причинам, которые я не понимаю, мне нужно использовать 2007b