2009-04-28 9 views

Respuesta

47

El function handle operator en MATLAB actúa esencialmente como un puntero a una instancia específica de una función. Algunas de las otras respuestas han discutido algunos de sus usos, pero añadiré otro uso aquí que a menudo tengo para él: mantener el acceso a las funciones que ya no están "dentro del alcance".

Por ejemplo, la siguiente función inicializa un valor count y, a continuación, devuelve un identificador de función a una función anidada increment:

function fHandle = start_counting(count) 

    disp(count); 
    fHandle = @increment; 

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

end 

Dado que la función increment es una nested function, sólo puede ser usado dentro de la función start_counting (es decir, el espacio de trabajo de start_counting es su "alcance"). Sin embargo, devolviendo un identificador a la función increment, aún puedo usarlo fuera de start_counting, y todavía conserva el acceso a las variables en el espacio de trabajo de start_counting! Eso permite que haga esto:

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

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

>> fh(); 
    5 

Aviso cómo podemos seguir incrementando la cuenta a pesar de que estamos fuera de la función start_counting. Pero se puede hacer algo aún más interesante llamando start_counting de nuevo con un número diferente y almacenar el identificador de función en otra variable:

>> 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 

en cuenta que estos dos contadores diferentes que operan de forma independiente. La función maneja los puntos fh y fh2 a diferentes instancias de la función increment con diferentes espacios de trabajo que contienen valores únicos para count.

Además de lo anterior, el uso de identificadores de función junto con funciones anidadas también puede ayudar a optimizar el diseño de la GUI, como lo ilustra en this other SO post.

+2

Una cosa que es importante tener en cuenta es que las funciones creadas con la palabra clave de función y las funciones creadas por el operador @ tienen diferentes reglas de ámbito. hGetCount = @ getCount; función c = getCount; c = conteo; fin; realiza la búsqueda de la variable de recuento en el momento de la evaluación (utilizando el alcance léxico), tal como lo describió anteriormente. La función hGetCount = @() cuenta; tendrá el valor de la variable de conteo sustituido en el momento de la creación. –

+2

Los identificadores de función le permiten trabajar con funciones anidadas o subfunciones, desde fuera de la función principal. Pueden ayudarte en la programación de la GUI. –

+0

@ Mr. Fooz: ¡Buen punto! Las funciones anónimas creadas con el operador @ simplemente sustituirán los valores de las variables que existen en el espacio de trabajo en el momento en que se crearon, mientras que las funciones "normales" tienen sus propios espacios de trabajo para almacenar variables. – gnovice

15

Exención de responsabilidad: Código no probado ...

El operador de la palanca función le permite crear una referencia a una función y pasa a su alrededor al igual que cualquier otra variable:

% 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 vez que haya tiene un mango función, se puede invocar al igual que una función regular:

operation(10, 20); % returns 30 

una cosa buena acerca de la función maneja es que se puede pasar a ellos en torno al igual que cualquier OTH er datos, para que pueda escribir funciones que actúen sobre otras funciones. A menudo, esto le permite separar fácilmente la lógica de negocio:

% 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')); 

El Matlab documentation tiene una descripción más completa de la sintaxis de Matlab, y describe algunos otros usos para la función se maneja como devoluciones de llamada gráficos.

17

Los identificadores de función son una herramienta extremadamente poderosa en matlab. Un buen comienzo es leer la ayuda en línea, que le dará mucho más de lo que puedo. En el símbolo del sistema, escriba

doc function_handle 

Un identificador de función es una manera simple de crear una función en una línea. Por ejemplo, supongamos que deseaba integrar numéricamente la función sin (k * x), donde k tiene algún valor externo fijo. Podría usar una función en línea, pero un identificador de función es mucho más ordenado. Definir una función

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

Ver que ahora puedo evaluar la función fofx en la línea de comandos. MATLAB sabe qué es k, así que ahora podemos usar fofx como una función.

fofx(0.3) 
ans = 
     0.564642473395035 

De hecho, podemos pasar fofx, efectivamente como una variable. Por ejemplo, llamemos a quad para hacer la integración numérica. Escogeré el intervalo [0, pi/2].

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

Como puede ver, quad hizo la integración numérica. (Por cierto, una función en línea hubiera sido por lo menos un orden de magitude más lenta, y mucho menos fácil de trabajar.)

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

A modo de comparación, intente una función en línea.

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

Lo bueno de un controlador de función es que puedes definirlo sobre la marcha. Minimice la función cos (x), durante el intervalo [0,2 * pi]?

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

Hay muchos, muchos otros usos para los identificadores de funciones en MATLAB. Solo arañé la superficie aquí.