2009-04-28 322 views

回答

47

MATLAB中的function handle operator实际上就像一个指向函数特定实例的指针。其他一些答案已经讨论了它的一些用途,但是我会在这里添加另一个我经常用到的用法:保持对不再“范围内”的函数的访问。

例如,下面的函数初始化的值count,然后返回的功能句柄到一个嵌套函数increment

function fHandle = start_counting(count) 

    disp(count); 
    fHandle = @increment; 

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

end 

由于函数incrementnested function,它只能在函数内使用start_counting(即start_counting的工作空间是其“范围”)。但是,通过返回increment函数的句柄,我仍然可以在start_counting之外使用它,并且它仍然保留访问start_counting工作空间中的变量的权限!这使我能够做到这一点:

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

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

>> fh(); 
    5 

通知我们怎样才能不断递增计数,即使我们是函数start_counting之外。但是你可以做更有趣用不同数量的再次调用start_counting和存储功能的手柄,另一个变量的东西:

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

请注意,这两个不同的计数器独立操作。该函数处理fhfh2指向函数increment的不同实例,其中不同的工作空间包含count的唯一值。

除上述之外,使用功能句柄和嵌套函数还可以帮助简化GUI设计,如我在this other SO post中所说明的。

+2

需要注意的一件事是,使用由@运算符创建的函数关键字和函数创建的函数具有不同的作用域规则。 hGetCount = @ getCount;函数c = getCount; C =计数;结束;如上所述,在评估时间(使用词法范围界定)查找count变量。函数hGetCount = @()计数;将在创建时替换count变量的值。 – 2009-04-28 13:53:00

15

免责声明:代码没有测试...

功能手柄操作允许你创建一个函数的引用,并通过它就像任何其他变量:

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

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

一旦你有一个功能手柄,你可以调用它就像一个普通的功能:

operation(10, 20); % returns 30 

一个关于功能很好的事情处理的是,你可以通过他们周围就像任何OTH呃数据,所以你可以编写对其他功能起作用的函数。这往往让您轻松分离出业务逻辑:

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

Matlab documentation有Matlab的语法的更详细的描述,并介绍了一些其他用途的函数处理如图形回调。

17

函数句柄是matlab中一个非常强大的工具。一个好的开始是阅读在线帮助,这会给你提供的帮助远远超过我的能力。在命令提示符下,键入

doc function_handle 

函数句柄是在一行中创建函数的简单方法。例如,假设我希望对函数sin(k * x)进行数值积分,其中k有一些固定的外部值。我可以使用内联函数,但函数句柄更简洁。定义函数

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

请参阅我现在可以在命令行评估函数fofx。 MATLAB知道k是什么,所以我们现在可以使用fofx作为函数。

fofx(0.3) 
ans = 
     0.564642473395035 

实际上,我们可以将fofx作为一个变量进行传递。例如,让我们调用quad来进行数值积分。我会选择间隔[0,pi/2]。

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

正如你所看到的,quad做了数值积分。 (顺便说一句,内联函数将是至少magitude的顺序慢,远不及易于使用。)

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

通过对比的方式,尝试内联函数。

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

关于函数句柄的一个整洁的东西是你可以在飞行中定义它。在区间[0,2 * pi]上最小化函数cos(x)?

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

MATLAB中的函数句柄有许多其他用途。我只是在这里表面划痕。