2009-04-28 16 views

risposta

47

Il function handle operator in MATLAB agisce essenzialmente come un puntatore a un'istanza specifica di una funzione. Alcune delle altre risposte hanno discusso alcuni dei suoi usi, ma qui aggiungerò un altro uso che spesso ho per questo: mantenere l'accesso a funzioni che non sono più "in ambito".

Ad esempio, la seguente funzione inizializza un valore count, e quindi restituisce una maniglia funzione a una funzione nidificata increment:

function fHandle = start_counting(count) 

    disp(count); 
    fHandle = @increment; 

    function increment 
    count = count+1; 
    disp(count); 
    end 

end 

Poiché la funzione increment è un nested function, esso può essere utilizzato solo all'interno della funzione start_counting (ovvero lo spazio di lavoro di start_counting è il suo "ambito"). Tuttavia, restituendo un handle alla funzione increment, posso ancora utilizzarlo al di fuori di start_counting e mantiene ancora l'accesso alle variabili nell'area di lavoro di start_counting! Che mi permette di fare questo:

>> fh = start_counting(3); % Initialize count to 3 and return handle 
    3 

>> fh(); % Invoke increment function using its handle 
    4 

>> fh(); 
    5 

Notate come possiamo mantenere l'incremento conteggio anche se siamo al di fuori della funzione start_counting. Ma si può fare qualcosa di ancora più interessante chiamando start_counting di nuovo con un numero diverso e memorizzare la maniglia funzione in un'altra variabile:

>> fh2 = start_counting(-4); 
    -4 

>> fh2(); 
    -3 

>> fh2(); 
    -2 

>> fh(); % Invoke the first handle to increment 
    6 

>> fh2(); % Invoke the second handle to increment 
    -1 

Si noti che questi due contatori diversi operano in modo indipendente. La funzione gestisce fh e fh2 in diverse istanze della funzione increment con aree di lavoro diverse contenenti valori univoci per count.

In aggiunta a quanto sopra, l'utilizzo di handle di funzione in combinazione con funzioni annidate può anche aiutare a semplificare la progettazione della GUI, come illustrato in this other SO post.

+2

Una cosa importante da notare è che le funzioni create con la parola chiave function e le funzioni create dall'operatore @ hanno regole di scoping diverse. hGetCount = @ getCount; funzione c = getCount; c = count; fine; fa la ricerca della variabile count al momento della valutazione (usando scope lessicale), come descritto sopra. La funzione hGetCount = @() conta; avrà il valore della variabile di conteggio sostituita al momento della creazione. –

+2

Gli handle di funzione consentono di lavorare con funzioni o sottofunzioni annidate, al di fuori della funzione principale. Possono aiutarti nella programmazione della GUI. –

+0

@ Mr. Fooz: buon punto! Le funzioni anonime create con l'operatore @ sostituiranno semplicemente i valori per le variabili esistenti nello spazio di lavoro nel momento in cui vengono create, mentre le funzioni "normali" hanno le proprie aree di lavoro per l'archiviazione delle variabili. – gnovice

15

Esonero di responsabilità: il codice non testato ...

L'operatore maniglia funzione consente di creare un riferimento a una funzione e passare in giro, proprio come qualsiasi altra variabile:

% function to add two numbers 
function total = add(first, second) 
    total = first + second; 
end 

% this variable now points to the add function 
operation = @add; 

Una volta che hai ha ottenuto una maniglia funzione, è possibile richiamare proprio come una normale funzione:

operation(10, 20); % returns 30 

una cosa bella di funzione gestisce è che si può passare in giro come qualsiasi OTH er i dati, in modo da poter scrivere funzioni che agiscono su altre funzioni. Questo spesso permette di separare facilmente fuori logica di business:

% prints hello 
function sayHello 
    disp('hello world!'); 
end 

% does something five times 
function doFiveTimes(thingToDo) 
    for idx = 1 : 5 
     thingToDo(); 
    end 
end 

% now I can say hello five times easily: 
doFiveTimes(@sayHello); 

% if there's something else I want to do five times, I don't have to write 
% the five times logic again, only the operation itself: 
function sayCheese 
    disp('Cheese'); 
end 
doFiveTimes(@sayCheese); 

% I don't even need to explicitly declare a function - this is an 
% anonymous function: 
doFiveTimes(@() disp('do something else')); 

Il Matlab documentation ha una descrizione più completa della sintassi Matlab, e descrive alcuni altri usi per la funzione di guida come callback grafiche.

17

Le maniglie di funzione sono uno strumento estremamente potente in MATLAB. Un buon inizio è leggere l'aiuto online, che ti darà molto più di me. Al prompt dei comandi, digitare

doc function_handle 

Un handle di funzione è un modo semplice per creare una funzione in una riga. Ad esempio, supponiamo di voler integrare numericamente la funzione sin (k * x), dove k ha un valore fisso, esterno. Potrei usare una funzione inline, ma una maniglia di funzione è molto più ordinata. Definire una funzione

k = 2; 
fofx = @(x) sin(x*k); 

Vedere che ora è possibile valutare la funzione fofx nella riga di comando. MATLAB sa cos'è k, quindi ora possiamo usare fofx come funzione.

fofx(0.3) 
ans = 
     0.564642473395035 

In effetti, possiamo passare fofx in giro, efficacemente come variabile. Ad esempio, consente di chiamare quad per eseguire l'integrazione numerica. Prenderò l'intervallo [0, pi/2].

quad(fofx,0,pi/2) 
ans = 
     0.999999998199215 

Come si può vedere, quad ha fatto l'integrazione numerica. (A proposito, una funzione inline sarebbe stato almeno un ordine di magitude più lento, e molto meno facile da lavorare.)

x = linspace(0,pi,1000); 
tic,y = fofx(x);toc 
Elapsed time is 0.000493 seconds. 

A titolo di confronto, provare una funzione inline.

finline = inline('sin(x*k)','x','k'); 
tic,y = finline(x,2);toc 
Elapsed time is 0.002546 seconds. 

Una cosa semplice di una maniglia funzione è che si può definire al volo. Ridurre al minimo la funzione cos (x), nell'intervallo [0,2 * pi]?

xmin = fminbnd(@(x) cos(x),0,2*pi) 
xmin = 
      3.14159265358979 

Ci sono molti, molti altri usi per le funzioni in MATLAB. Ho solo graffiato la superficie qui.