Что такое дескриптор функции и чем он полезен?

37

Может ли кто-нибудь объяснить мне смысл оператора @ (function handle) и почему его использовать?

Теги:
function
function-handle

3 ответа

50
Лучший ответ

Оператор дескриптора функции в MATLAB действует по существу как указатель на конкретный экземпляр функции. Некоторые из других ответов обсудили некоторые из его применений, но я добавлю еще одно использование здесь, которое у меня часто для него: сохранение доступа к функциям, которые больше не "в области видимости".

Например, следующая функция инициализирует count значений, а затем возвращает дескриптор функции в increment вложенной функции:

function fHandle = start_counting(count)

  disp(count);
  fHandle = @increment;

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

end

Поскольку increment функции является вложенной функцией, ее можно использовать только в функции start_counting (т. 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

Обратите внимание, что эти два разных счетчика работают независимо. Функция обрабатывает fh и fh2 на разные экземпляры increment функции с разными рабочими пространствами, содержащими уникальные значения для count.

В дополнение к вышесказанному, использование дескрипторов функций в сочетании с вложенными функциями также может помочь оптимизировать дизайн графического интерфейса, как я иллюстрирую в этом другом сообщении SO.

  • 2
    Важно отметить, что функции, созданные с помощью ключевого слова function, и функции, созданные оператором @, имеют разные правила области видимости. hGetCount = @ getCount; function c = getCount; с = кол; конец; выполняет поиск переменной count во время оценки (используя лексическую область видимости), как вы описали выше. Функция hGetCount = @ () count; будет подставлено значение переменной count во время создания.
  • 2
    Дескрипторы функций позволяют работать с вложенными функциями или подфункциями извне основной функции. Они могут помочь вам в программировании GUI.
Показать ещё 1 комментарий
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 сделал численное интегрирование. (Кстати, встроенная функция была бы, по меньшей мере, порядка магии медленнее и с гораздо меньшей легкостью работать.)

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.

Умная вещь о дескрипторе функции - вы можете определить ее на лету. Минимизируем функцию cos (x) на интервале [0,2 * pi]?

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

В MATLAB используется много и много других функций для обработки функций. Я только поцарапал поверхность здесь.

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

Одна хорошая вещь о дескрипторах функций заключается в том, что вы можете передавать их так же, как и любые другие данные, чтобы вы могли писать функции, которые действуют на другие функции. Это часто позволяет легко отделить бизнес-логику:

% 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 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 содержит более подробное описание синтаксиса Matlab и описывает некоторые другие функции для дескрипторов функций, таких как обратные вызовы графики.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню