Come eseguire più istruzioni in una funzione anonima MATLAB?

Mi piacerebbe fare qualcosa di simile a questo:

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

Così quando ho detto:

 >> foo() 

Dovrebbe eseguire functionCall1() e quindi eseguire functionCall2() . (Sento che ho bisogno di qualcosa come il C, operatore )

MODIFICARE:

functionCall1 e functionCall2 non sono necessariamente funzioni che restituiscono valori.

Provare a fare tutto tramite la riga di comando senza salvare le funzioni nei m-file può essere uno sforzo complicato e disordinato, ma ecco un modo in cui mi sono inventato …

Per prima cosa, crea le tue funzioni anonime e metti le loro maniglie in un array di celle :

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

… o, se hai già delle funzioni definite (come in m-files), posiziona i manici di funzione in un array di celle in questo modo:

 fcnArray = {@fcn1 @fcn2 @fcn3}; 

Quindi puoi creare una nuova funzione anonima che chiama ogni funzione nell’array usando le funzioni built-in cellfun e feval :

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

Anche se dall’aspetto divertente, funziona.

EDIT: Se le funzioni in fcnArray devono essere richiamate con argomenti di input, è necessario prima assicurarsi che TUTTE le funzioni dell’array richiedano il numero di input SAME. In tal caso, l’esempio seguente mostra come chiamare la matrice di funzioni con un argomento di input ciascuno:

 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 

PAROLA DI AVVERTENZA: la documentazione per cellfun afferma che l’ ordine in cui gli elementi di output sono calcolati non è specificato e non dovrebbe essere invocato. Ciò significa che non ci sono garanzie che fcn1 venga valutato prima di fcn2 o fcn3 . Se l’ordine è importante, la soluzione di cui sopra non deve essere utilizzata.

La syntax della funzione anonima in Matlab (come alcuni altri linguaggi) consente solo un’espressione singola. Inoltre, ha una semantica di binding variabile diversa (le variabili che non sono nella lista degli argomenti hanno i loro valori legati lessicamente al momento della creazione della funzione, invece dei riferimenti che sono vincolati). Questa semplicità consente a Mathworks di eseguire alcune ottimizzazioni dietro le quinte ed evitare molti problemi di scope e durata dell’object durante il loro utilizzo negli script.

Se si sta definendo questa funzione anonima all’interno di una funzione (non uno script), è ansible creare funzioni interne denominate. Le funzioni interne hanno un normale legame lessicale di riferimento e consentono numeri arbitrari di affermazioni.

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

A volte puoi farcela con trucchi come il suggerimento di gnovice.

Fai attenzione all’utilizzo di eval … è molto inefficiente (aggira il JIT), e l’ottimizzatore di Matlab può confondersi tra variabili e funzioni dall’ambito esterno che vengono utilizzate all’interno dell’espressione eval. È anche difficile eseguire il debug e / o il codice di estensione che utilizza eval.

Ecco un metodo che garantirà l’ordine di esecuzione e, (con le modifiche menzionate alla fine) consente di passare argomenti diversi a funzioni diverse.

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

La chiave è call1 che chiama il suo primo argomento e ignora il suo secondo. call12 chiama il suo primo argomento e poi il suo secondo, restituendo il valore dal secondo. Funziona perché una funzione non può essere valutata prima dei suoi argomenti. Per creare il tuo esempio, dovresti scrivere:

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

Codice di prova

Ecco il codice di prova che ho usato:

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

Chiamando più funzioni

Per chiamare 3 funzioni, potresti scrivere

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

4 funzioni:

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

Per ulteriori funzioni, continua il modello di nidificazione.

Passando argomenti

Se è necessario passare argomenti, è ansible scrivere una versione di call1 che accetta argomenti e quindi effettua la modifica ovvia per 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)) 

Puoi anche creare versioni di call1 che accettano più argomenti e mescolarli e abbinarli a seconda dei casi.

Se functionCall1() e functionCall2() restituiscono qualcosa e quei qualcosa possono essere concatenati, puoi farlo:

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

o

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

Un effetto collaterale di ciò è che foo() restituirà la concatenazione di qualunque functionCall1() e functionCall2() restituiscono.

Non so se l’ordine di esecuzione di functionCall1() e functionCall2() è garantito.

È ansible, usando la funzione Ricci che è usata per creare una lista separata da virgola.

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

Forse mi manca qualcosa, basta creare una combinazione di funzioni che chiama entrambe le funzioni per te.