ラムダ関数とクロージャー

画像 もちろん、私たちの多くはこの概念に精通していますが、この記事は初心者を対象としています。 この投稿では、この現象を検討し、使用例を示します。 最初に、ラムダ関数とは何かを理解する必要があります。 したがって、ラムダ関数は、しばしば匿名と呼ばれます。つまり、定義で名前を指定する必要のない関数です。 そのような関数の戻り値は、この関数を後で呼び出すことができる変数に割り当てられます。

PHP 5.3より前では、ラムダ関数を定義できましたが、完全に呼び出すことはできませんでした。 次に、いくつかの例を挙げて、これらの概念について引き続き検討します。

<?php $temp = create_function( '$match', 'return (preg_match(\'/^{(.*)}$/\',$match[1],$m) ? "cms_$m[1]" : $match[1]);'); $query = 'SELECT * FROM {documents}'; $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'; echo preg_replace_callback($regExp, $temp, $query); // SELECT * FROM cms_documents ?>
      
      





もちろん、関数を動的に作成してもすべての問題が解決されるわけではありませんが、そのような1回限りの関数を作成すると役立つ場合があります。 サンプルを展開できます。

 <?php class Builder { private $query; private $prefix; public function __construct($prefix='' ) { $this->query = $query; $this->prefix = $prefix; } public function replaceCallback( $match ) { return ( preg_match('/^{(.*)}$/',$match[1],$m) ? ( empty($this->prefix) ? $m[1] : "{$this->prefix}_$m[1]" ) : $match[1] ); } public function build($query) { static $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'; return preg_replace_callback($regExp, array(&$this, "replaceCallback"), $query); } }; $builder = new Builder('cms'); echo $builder->build(“SELECT * FROM {documents}”); // SELECT * FROM cms_documents ?>
      
      





閉鎖の概念は、おそらくJavaScriptプログラマーだけでなく、他の多くの言語のプログラマーにもよく知られています。 クロージャーとは、現在のスコープをスパンまたはクローズする関数です。 これをすべて理解するために、例を考えてみましょう。

 <?php $x = function( $number ) { return $number * 10; }; echo $x(8); //  80 ?>
      
      





お気づきかもしれませんが、関数には名前がなく、結果は変数に割り当てられます。 この方法で作成されたラムダ関数は、クロージャー型のオブジェクトの形式で値を返します。

PHP 5.3では、オブジェクトを関数であるかのように呼び出すことが可能になりました。 つまり、魔法の__invoke()メソッドは、クラスが関数として呼び出されるたびに呼び出されます。

グローバルで宣言されていない限り、変数は関数内で使用できません。また、子コンテキストからの変数は、予約語useを使用しない限り使用できません。 通常、PHPでは、変数は値とともにクロージャーに渡されます;この動作は、useステートメントの変数の前にあるアンパサンドを使用して変更できます。 例を考えてみましょう:

 <?php class ClosureTest { public $multiplier; public function __construct( $multilier ) { $this->multiplier = $multilier; } public function getClosure() { $mul = &$this->multiplier; return function( $number ) use( &$mul ) { return $mul * $number; }; } } $test = new ClosureTest(10); $x = $test->getClosure(); echo $x(8); //  80 $test->multiplier = 2; echo $x(8); //  16 ?>
      
      





アンパーサンドを削除すると、クロージャー内の$ mul変数はリンクではなくコピーになるため、80回が両方の時間に表示されます。

そのため、実際にこれをどのように適用できるかを知るだけです。

例を考えてみましょう:

 <?php class QueryBuilder extends Builder { public function getQueryObject($query) { $self = $this; return function() use ($self,$query) { $argv = func_get_args(); foreach ( $argv as $i => $arg ) $argv[$i] = mysql_escape_string($arg); array_unshift($argv, $self->build($query)); return call_user_func_array( “sprintf”, $argv); }; } }; $builder = new QueryBuilder(); $deleteBook = $builder->getQueryObject(“DELETE FROM {documents} WHERE id=%d”); $deleteBook( $_GET['id'] ); ?>
      
      





この例は、すでに柔軟なプロトタイピングに使用できます。 オブジェクトを使用して、すべてのSQL操作のメソッドを宣言するだけで十分です。

著者は、誰もがこの慣行に従うように促したり、それが優れているとは考えていません。上記のすべては単なる使用例であり、おそらく最も技術的で興味深いものではなく、それ以上ではありません。

UPDその非常に長い正規表現と言えば、コメントに署名せず、ここに置くことにしました。 テーブル名だけでなく、一重引用符と二重引用符で文字列を検索し、それらをエスケープします。



All Articles