2009-04-28 32 views

Trả lời

47

Các function handle operator trong MATLAB hoạt động cơ bản giống như một con trỏ đến một phiên bản cụ thể của hàm. Một số câu trả lời khác đã thảo luận một vài cách sử dụng của nó, nhưng tôi sẽ thêm một cách sử dụng khác ở đây mà tôi thường sử dụng: duy trì quyền truy cập vào các hàm không còn "trong phạm vi" nữa.

Ví dụ, hàm sau khởi tạo một giá trị count, và sau đó trả về một chức năng xử lý tới một hàm lồng nhau increment:

function fHandle = start_counting(count) 

    disp(count); 
    fHandle = @increment; 

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

end 

Kể từ khi chức năng increment là một nested function, nó chỉ có thể được sử dụng trong phạm vi chức năng start_counting (nghĩa là không gian làm việc của start_counting là "phạm vi" của nó). Tuy nhiên, bằng cách trả về một tay cầm cho hàm increment, tôi vẫn có thể sử dụng nó bên ngoài start_counting và nó vẫn giữ quyền truy cập vào các biến trong không gian làm việc của start_counting! Điều đó cho phép tôi thực hiện việc này:

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

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

>> fh(); 
    5 

Lưu ý cách chúng tôi có thể tăng số lượng mặc dù chúng tôi ở bên ngoài chức năng start_counting. Nhưng bạn có thể làm điều gì đó thú vị hơn bằng cách gọi start_counting một lần nữa với một số khác nhau và lưu trữ các chức năng xử lý trong một biến khác:

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

Chú ý rằng hai quầy khác nhau hoạt động độc lập. Hàm xử lý fhfh2 trỏ đến các phiên bản khác nhau của hàm increment với không gian làm việc khác nhau chứa các giá trị duy nhất cho count.

Ngoài các chức năng trên, việc sử dụng các chức năng xử lý kết hợp với các hàm lồng nhau cũng có thể giúp hợp lý hóa thiết kế GUI, như minh họa trong this other SO post.

+2

Một điều quan trọng cần lưu ý là các hàm được tạo bằng từ khóa hàm và hàm do toán tử @ tạo ra có các quy tắc phạm vi khác nhau. hGetCount = @ getCount, hàm c = getCount; c = đếm; kết thúc; không tra cứu biến số đếm tại thời điểm đánh giá (sử dụng phạm vi từ vựng), như bạn mô tả ở trên. Hàm hGetCount = @() đếm; sẽ có giá trị của biến số đếm thay thế tại thời gian tạo. –

+2

Xử lý chức năng cho phép bạn làm việc với các chức năng lồng nhau hoặc các chức năng con, từ bên ngoài chức năng chính. Họ có thể hỗ trợ bạn trong lập trình GUI. –

+0

@ Ông Fooz: Tốt! Các hàm ẩn danh được tạo bằng toán tử @ sẽ chỉ thay thế các giá trị cho các biến tồn tại trong không gian làm việc tại thời điểm chúng được tạo, trong khi các hàm "bình thường" có không gian làm việc riêng để lưu trữ các biến. – gnovice

15

Disclaimer: Mã không được kiểm tra ...

Nhà điều hành chức năng xử lý cho phép bạn tạo một tham chiếu đến một chức năng và vượt qua nó xung quanh giống như bất kỳ biến khác:

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

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

Một khi bạn đã có một chức năng xử lý, bạn có thể gọi nó như một chức năng thông thường:

operation(10, 20); % returns 30 

Một điều tốt đẹp về xử lý chức năng là bạn có thể truyền chúng xung quanh giống như bất kỳ oth er dữ liệu, vì vậy bạn có thể viết các hàm hoạt động trên các chức năng khác. Điều này thường cho phép bạn dễ dàng tách ra logic kinh doanh:

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

Các Matlab documentation có một mô tả đầy đủ hơn về cú pháp Matlab và mô tả một số công dụng khác cho chức năng xử lý như callbacks đồ họa.

17

Xử lý chức năng là một công cụ cực kỳ mạnh mẽ trong MATLAB. Một khởi đầu tốt là đọc trợ giúp trực tuyến, điều này sẽ giúp bạn có nhiều hơn tôi có thể. Tại dấu nhắc lệnh, nhập

doc function_handle 

Xử lý chức năng là cách đơn giản để tạo hàm trong một dòng. Ví dụ, giả sử tôi muốn tích hợp số lượng hàm sin (k * x), trong đó k có một số giá trị ngoài cố định. Tôi có thể sử dụng một chức năng nội tuyến, nhưng một chức năng xử lý là nhiều neater. Xác định hàm

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

Xem bây giờ tôi có thể đánh giá hàm fofx tại dòng lệnh. MATLAB biết k là gì, vì vậy chúng ta có thể sử dụng fofx như một hàm ngay bây giờ.

fofx(0.3) 
ans = 
     0.564642473395035 

Thực tế, chúng ta có thể chuyển qua fofx, hiệu quả như biến. Ví dụ, cho phép gọi quad để thực hiện tích hợp số. Tôi sẽ chọn khoảng [0, pi/2].

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

Như bạn thấy, quad đã tích hợp số. (Bằng cách này, một hàm nội tuyến sẽ có được ít nhất một thứ tự của magitude chậm hơn, và ít dễ dàng để làm việc với.)

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

Bằng cách so sánh, hãy thử một hàm nội tuyến.

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

Điều gọn gàng về trình xử lý chức năng là bạn có thể xác định nó ngay lập tức. Giảm thiểu hàm cos (x), trong khoảng [0,2 * pi]?

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

Có rất nhiều, nhiều ứng dụng khác cho xử lý chức năng trong MATLAB. Tôi đã chỉ trầy xước bề mặt ở đây.

Các vấn đề liên quan