web-dev-qa-db-ja.com

関数ハンドルとは何ですか?

誰かが@(関数ハンドル)演算子の意味とそれを使用する理由を説明できますか?

38
Dikla

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のワークスペースはその「スコープ」です) 。ただし、関数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

これら2つの異なるカウンターは独立して動作することに注意してください。この関数は、fhおよびfh2ポイントを処理し、incrementの一意の値を含むさまざまなワークスペースで関数countの異なるインスタンスをポイントします。

上記に加えて、ネストされた関数と組み合わせて関数ハンドルを使用すると、 this other SO post

49
gnovice

関数ハンドルは、Matlabの非常に強力なツールです。良い出発点は、オンラインヘルプを読むことです。コマンドプロンプトで、次のように入力します

doc function_handle

関数ハンドルは、1行で関数を作成する簡単な方法です。たとえば、関数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は数値積分を行いました。 (ちなみに、インライン関数は少なくとも1桁遅くなり、操作がはるかに簡単になります。)

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の関数ハンドルには、他にも多くの用途があります。ここで表面をひっかいただけです。

18
user85109

免責事項:コードはテストされていません...

関数ハンドル演算子を使用すると、関数への参照を作成し、他の変数と同じように渡すことができます。

% 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

関数ハンドルの良い点の1つは、他のデータと同じように渡すことができるため、他の関数に作用する関数を作成できることです。これにより、多くの場合、ビジネスロジックを簡単に分離できます。

% 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ドキュメンテーション には、Matlab構文の詳細な説明があり、グラフィックスコールバックなどの関数ハンドルのその他の使用法について説明しています。

15
Dan Vinton