Подтвердить что ты не робот

Как выполнить несколько операторов в анонимной функции MATLAB?

Я хотел бы сделать что-то вроде этого:

>> foo = @() functionCall1() functionCall2()

Итак, когда я сказал:

>> foo()

Он выполнит functionCall1(), а затем выполнит functionCall2(). (Я чувствую, что мне нужно что-то вроде оператор C)

EDIT:

functionCall1 и functionCall2 не обязательно являются функциями, возвращающими значения.

4b9b3361

Ответ 1

Попытка сделать все через командную строку без сохранения функций в 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. Если порядок имеет значение, вышеуказанное решение не должно использоваться.

Ответ 2

Синтаксис анонимной функции в 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.

Ответ 3

Вот метод, который будет гарантировать порядок выполнения и (с модификациями, упомянутыми в конце) позволяет передавать разные аргументы различным функциям.

call1 = @(a,b) a();
call12 = @(a,b) call1(b,call1(a,b));

Ключ call1, который вызывает свой первый аргумент и игнорирует его второй. call12 вызывает свой первый аргумент, а затем второй, возвращая значение из второго. Он работает, потому что функция не может быть оценена перед ее аргументами. Чтобы создать свой пример, вы должны написать:

foo = @() call12(functionCall1, functionCall2);

Тестовый код

Вот тестовый код, который я использовал:

>> [email protected]()fprintf('1\n');
>> [email protected]()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, которые принимают несколько аргументов и смешивают и сопоставляют их по мере необходимости.

Ответ 4

Если functionCall1() и functionCall2() возвращают что-то, и эти somethings могут быть объединены, вы можете сделать это:

>> foo = @() [functionCall1(), functionCall2()]

или

>> foo = @() [functionCall1(); functionCall2()]

Побочным эффектом этого является то, что foo() вернет конкатенацию любых functionCall1() и functionCall2().

Я не знаю, гарантирован ли порядок выполнения functionCall1() и functionCall2().

Ответ 5

Возможно, используя функцию curly, которая используется для создания списка, разделенного запятой.

curly = @(x, varargin) x{varargin{:}};
[email protected](x)curly({exp(x),log(x)})
[a,b]=f(2)

Ответ 6

Возможно, мне не хватает somethign, просто создайте функцию combCall, которая вызывает обе функции для вас.