7

Pythonでは、次のことができます。

def foo(param1, param2):
    def bar():
        print param1 + param2
    bar()

しかし、PHPでのこの動作にはいくつかの問題があります。私はこれが次のように機能することを期待しています:

function foo($param1, $param2)
{
    function bar()
    {
        echo $param1 + $param2;
    }
    bar();
}

しかし、それは失敗します。だから私はクロージャについていくつか読んだ(これはクロージャと呼ばれているのではないか?それはPythonである、私が知っている)。また、無名関数(クロージャとして実装されていると言われています)に関するphpドキュメントでは、use()式を次のように使用するように指示されています。

function foo($param1, $param2)
{
    function bar() use($param1, $param2)
    {
        echo $param1 + $param2;
    }
    bar();
}

しかし、それでも失敗します。そこで、次のようにPHPの無名関数aに変更しました。

function foo($param1, $param2)
{
    $bar = function() use($param1, $param2)
    {
        echo $param1 + $param2;
    };
    $bar();
}

それは機能しますが、本当に醜いように見えます。私は何かが足りないのですか?これを何らかの方法で改善できますか?それとも、「醜い」方法を使用する必要がありますか?

(私は閉鎖が有用であるかどうかについての議論を探していません)

4

3 に答える 3

4

function bar() use($param1, $param2)リンク先のマニュアルページで構文が見つかりませんでした。機能する「醜い」バージョン(本当に匿名)だけです。私はあなたがそれを使わなければならないだろうと思います。

2番目の例でbarは、はクロージャではありません。PHPでクロージャを作成するには、醜いuse、またはClosureクラスを使用する必要があります。すべての関数は独自のローカルスコープを作成しますが、クロージャは自動ではありません。

マニュアルを読んだときにおそらくお気づきのように、PHPには「閉鎖」という用語の奇妙な定義があるようです。彼らはそれを「無名関数」の同義語として定義しています。

クロージャとも呼ばれる無名関数(...)

紛らわしいですよね?use後で、親スコープを継承する場合はキーワードが必要であると説明します。

クロージャは、親スコープから変数を継承する場合もあります。このような変数はすべて、関数ヘッダーで宣言する必要があります。

クロージャに関するPHPWikirfcページには、クロージャがこのように実装された理由に関するヒントがいくつかあります。

PHPのスコープの概念は、他の言語が定義するスコープの概念とはまったく異なります。これを変数変数($$ var)と組み合わせると、外部スコープのどの変数が内部で参照されているかを自動的に検出することは不可能であることが明らかになります。また、たとえばグローバル変数はデフォルトでは関数内にも表示されないため、親スコープを自動的に使用可能にすると、PHPが従う現在の言語の概念に違反します。

于 2012-06-01T14:43:51.330 に答える
1

PHPでは、中間スコープにアクセスすることはできません。ローカルスコープとグローバルスコープのみがあります。これは、PHPの逆スコープルールのアーティファクトであり、正気の言語のスコープルールとは正反対です。

于 2012-06-01T14:43:19.347 に答える
1

PHPでは、名前付き関数宣言(function bar ())はグローバルスコープで関数を宣言します。したがって、最初の例では、関数を実行すると、グローバルスコープで関数fooが定義され、の外で宣言したかのように、誰でも関数にアクセスできます。PHPでは、関数と変数は別々です。名前付き関数のスコープは1つだけです。ローカル変数がありますが、ローカルスコープの関数などはありません。barbarfoo

言い換えれば、それを中に入れることfooは幻想です。名前付き関数宣言は常にグローバルに宣言します。内部にfoo配置すると、宣言が実行されるまでの時間が遅延します(したがって、宣言が定義されるときに遅延します)foo

クロージャはあなたが必要とするものです。他の答えはあなたにそれをする方法を示しました。

于 2012-06-01T18:14:52.103 に答える