How to execute multiple statements in a MATLAB ano

2019-01-03 10:14发布

I'd like to do something like this:

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

So that when I said:

>> foo()

It would execute functionCall1() and then execute functionCall2(). (I feel that I need something like the C , operator)

EDIT:

functionCall1 and functionCall2 are not necessarily functions that return values.

6条回答
在下西门庆
2楼-- · 2019-01-03 10:24

It is possible, using the curly function which is used to create a comma separated list.

curly = @(x, varargin) x{varargin{:}};
f=@(x)curly({exp(x),log(x)})
[a,b]=f(2)
查看更多
冷血范
3楼-- · 2019-01-03 10:25

Trying to do everything via the command line without saving functions in m-files may be a complicated and messy endeavor, but here's one way I came up with...

First, make your anonymous functions and put their handles in a cell array:

fcn1 = @() ...;
fcn2 = @() ...;
fcn3 = @() ...;
fcnArray = {fcn1 fcn2 fcn3};

...or, if you have functions already defined (like in m-files), place the function handles in a cell array like so:

fcnArray = {@fcn1 @fcn2 @fcn3};

Then you can make a new anonymous function that calls each function in the array using the built-in functions cellfun and feval:

foo = @() cellfun(@feval,fcnArray);

Although funny-looking, it works.

EDIT: If the functions in fcnArray need to be called with input arguments, you would first have to make sure that ALL of the functions in the array require THE SAME number of inputs. In that case, the following example shows how to call the array of functions with one input argument each:

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


WORD OF WARNING: The documentation for cellfun states that the order in which the output elements are computed is not specified and should not be relied upon. This means that there are no guarantees that fcn1 gets evaluated before fcn2 or fcn3. If order matters, the above solution shouldn't be used.

查看更多
Fickle 薄情
4楼-- · 2019-01-03 10:33

The anonymous function syntax in Matlab (like some other languages) only allows a single expression. Furthermore, it has different variable binding semantics (variables which are not in the argument list have their values lexically bound at function creation time, instead of references being bound). This simplicity allows Mathworks to do some optimizations behind the scenes and avoid a lot of messy scoping and object lifetime issues when using them in scripts.

If you are defining this anonymous function within a function (not a script), you can create named inner functions. Inner functions have normal lexical reference binding and allow arbitrary numbers of statements.

function F = createfcn(a,...)
  F = @myfunc;
  function b = myfunc(...)
    a = a+1; 
    b = a; 
  end
end

Sometimes you can get away with tricks like gnovice's suggestion.

Be careful about using eval... it's very inefficient (it bypasses the JIT), and Matlab's optimizer can get confused between variables and functions from the outer scope that are used inside the eval expression. It's also hard to debug and/or extent code that uses eval.

查看更多
该账号已被封号
5楼-- · 2019-01-03 10:40

If functionCall1() and functionCall2() return something and those somethings can be concatenated, then you can do this:

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

or

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

A side effect of this is that foo() will return the concatenation of whatever functionCall1() and functionCall2() return.

I don't know if the execution order of functionCall1() and functionCall2() is guaranteed.

查看更多
老娘就宠你
6楼-- · 2019-01-03 10:44

Here is a method that will guarantee execution order and, (with modifications mentioned at the end) allows passing different arguments to different functions.

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

The key is call1 which calls its first argument and ignores its second. call12 calls its first argument and then its second, returning the value from the second. It works because a function cannot be evaluated before its arguments. To create your example, you would write:

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

Test Code

Here is the test code I used:

>> print1=@()fprintf('1\n');
>> print2=@()fprintf('2\n');
>> call12(print1,print2)
1
2

Calling more functions

To call 3 functions, you could write

call1(print3, call1(print2, call1(print1,print2)));

4 functions:

call1(print4, call1(print3, call1(print2, call1(print1,print2))));

For more functions, continue the nesting pattern.

Passing Arguments

If you need to pass arguments, you can write a version of call1 that takes arguments and then make the obvious modification to 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))

You can also make versions of call1 that take multiple arguments and mix and match them as appropriate.

查看更多
老娘就宠你
7楼-- · 2019-01-03 10:46

Maybe I am missing somethign, just make a function combinationCall that calls both functions for you.

查看更多
登录 后发表回答