Ai đó có thể giải thích cho tôi ý nghĩa của nhà điều hành @
(chức năng xử lý) và tại sao sử dụng nó?Chức năng xử lý là gì và nó hữu ích như thế nào?
Trả lời
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ý fh
và fh2
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.
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.
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.
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. –
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. –
@ Ô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