Я хотел бы сделать что-то вроде этого:
>> foo = @() functionCall1() functionCall2()
Итак, когда я сказал:
>> foo()
Он выполнит functionCall1()
, а затем выполнит functionCall2()
. (Я чувствую, что мне нужно что-то вроде оператор C)
EDIT:
functionCall1
и functionCall2
не обязательно являются функциями, возвращающими значения.
Попытка сделать все через командную строку без сохранения функций в m файлах может быть сложной и запутанной задачей, но здесь одним из способов я придумал...
Сначала сделайте анонимные функции и поместите их handles в массиве :
fcn1 = @() ...;
fcn2 = @() ...;
fcn3 = @() ...;
fcnArray = {fcn1 fcn2 fcn3};
... или, если у вас есть уже определенные функции (например, в m файлах), поместите функции в массив ячеек следующим образом:
fcnArray = {@fcn1 @fcn2 @fcn3};
Затем вы можете создать новую анонимную функцию, которая вызывает каждую функцию в массиве с помощью встроенных функций cellfun
и feval
:
foo = @() cellfun(@feval,fcnArray);
Несмотря на забавный вид, он работает.
EDIT: Если функции в fcnArray
должны быть вызваны с входными аргументами, вам сначала нужно убедиться, что для ВСЕХ функций в массиве требуется ИСТОЧНИЕ количество входов. В этом случае в следующем примере показано, как вызвать массив функций с одним входным аргументом каждый:
foo = @(x) cellfun(@feval,fcnArray,x);
inArgs = {1 'a' [1 2 3]};
foo(inArgs); %# Passes 1 to fcn1, 'a' to fcn2, and [1 2 3] to fcn3
СЛОВО ПРЕДУПРЕЖДЕНИЯ: В документации для cellfun
указано, что порядок, в котором вычисляются выходные элементы, не указан и на него нельзя положиться. Это означает, что нет гарантий, что fcn1
оценивается до fcn2
или fcn3
. Если порядок имеет значение, вышеуказанное решение не должно использоваться.
myfun = @() cellfun(@feval,{@() xlim([1 5]), @() xlabel('seconds')});
Теперь вызов myfun установит на рисунке и xlim, и xlabel.
Синтаксис анонимной функции в Matlab (как и некоторые другие языки) допускает только одно выражение. Кроме того, он имеет различную семантику связывания переменных (переменные, которые не входят в список аргументов, имеют свои значения, лексически связанные во время создания функции, а не связанные ссылки). Эта простота позволяет Mathworks делать некоторые оптимизации за кулисами и избегать множества проблем с охватом и проблемами времени жизни при использовании их в сценариях.
Если вы определяете эту анонимную функцию внутри функции (а не script), вы можете создавать именованные внутренние функции. Внутренние функции имеют нормальное лексическое связывание ссылок и позволяют произвольное количество операторов.
function F = createfcn(a,...)
F = @myfunc;
function b = myfunc(...)
a = a+1;
b = a;
end
end
Иногда вы можете уйти с трюками, такими как предложение gnovice.
Будьте осторожны с использованием eval... он очень неэффективен (он обходит JIT), а оптимизатор Matlab может запутаться между переменными и функциями из внешней области, которые используются внутри выражения eval. Также сложно отлаживать и/или расширять код, который использует eval.
Вот метод, который будет гарантировать порядок выполнения и (с модификациями, упомянутыми в конце) позволяет передавать разные аргументы различным функциям.
call1 = @(a,b) a();
call12 = @(a,b) call1(b,call1(a,b));
Ключ call1
, который вызывает свой первый аргумент и игнорирует его второй. call12
вызывает свой первый аргумент, а затем второй, возвращая значение из второго. Он работает, потому что функция не может быть оценена перед ее аргументами. Чтобы создать свой пример, вы должны написать:
foo = @() call12(functionCall1, functionCall2);
Тестовый код
Вот тестовый код, который я использовал:
>> print1=@()fprintf('1\n');
>> print2=@()fprintf('2\n');
>> call12(print1,print2)
1
2
Вызов дополнительных функций
Чтобы вызвать 3 функции, вы можете написать
call1(print3, call1(print2, call1(print1,print2)));
4 функции:
call1(print4, call1(print3, call1(print2, call1(print1,print2))));
Для получения дополнительных функций продолжите шаблон вложенности.
Передача аргументов
Если вам нужно передать аргументы, вы можете написать версию call1
, которая принимает аргументы, а затем делает очевидную модификацию call12
.
call1arg1 = @(a,arg_a,b) a(arg_a);
call12arg1 = @(a, arg_a, b, arg_b) call1arg1(b, arg_b, call1arg1(a, arg_a, b))
Вы также можете создавать версии call1, которые принимают несколько аргументов и смешивают и сопоставляют их по мере необходимости.
Возможно, используя функцию curly, которая используется для создания списка, разделенного запятой.
curly = @(x, varargin) x{varargin{:}};
f=@(x)curly({exp(x),log(x)})
[a,b]=f(2)
Если functionCall1()
и functionCall2()
возвращают что-то, и эти somethings могут быть объединены, вы можете сделать это:
>> foo = @() [functionCall1(), functionCall2()]
или
>> foo = @() [functionCall1(); functionCall2()]
Побочным эффектом этого является то, что foo()
вернет конкатенацию любых functionCall1()
и functionCall2()
.
Я не знаю, гарантирован ли порядок выполнения functionCall1()
и functionCall2()
.
Возможно, мне не хватает somethign, просто создайте функцию combCall, которая вызывает обе функции для вас.