閉包的文法很簡單,需要注意的關鍵字就隻有use,use意思是連接配接閉包和外界變量。
1
2
3
<code>$a</code> <code>=</code><code>function</code><code>()</code><code>use</code><code>(</code><code>$b</code><code>) {</code>
<code>}</code>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<code><?php</code>
<code>// 一個基本的購物車,包括一些已經添加的商品和每種商品的數量。</code>
<code>// 其中有一個方法用來計算購物車中所有商品的總價格。該方法使用了一個closure作為回調函數。</code>
<code>class</code> <code>cart</code>
<code>{</code>
<code> </code><code>const</code> <code>price_butter = 1.00;</code>
<code> </code><code>const</code> <code>price_milk = 3.00;</code>
<code> </code><code>const</code> <code>price_eggs = 6.95;</code>
<code> </code><code>protected</code> <code>$products</code> <code>=</code><code>array</code><code>();</code>
<code> </code>
<code> </code><code>public</code> <code>function</code> <code>add(</code><code>$product</code><code>,</code><code>$quantity</code><code>)</code>
<code> </code><code>{</code>
<code> </code><code>$this</code><code>->products[</code><code>$product</code><code>] =</code><code>$quantity</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>function</code> <code>getquantity(</code><code>$product</code><code>)</code>
<code> </code><code>return</code> <code>isset(</code><code>$this</code><code>->products[</code><code>$product</code><code>]) ?</code><code>$this</code><code>->products[</code><code>$product</code><code>] :</code>
<code> </code><code>false;</code>
<code> </code><code>public</code> <code>function</code> <code>gettotal(</code><code>$tax</code><code>)</code>
<code> </code><code>$total</code> <code>= 0.00;</code>
<code> </code>
<code> </code><code>$callback</code> <code>=</code>
<code> </code><code>function</code> <code>(</code><code>$quantity</code><code>,</code><code>$product</code><code>)</code><code>use</code> <code>(</code><code>$tax</code><code>, &</code><code>$total</code><code>)</code>
<code> </code><code>{</code>
<code> </code><code>$priceperitem</code> <code>= constant(</code><code>__class__</code> <code>.</code><code>"::price_"</code> <code>.</code>
<code> </code><code>strtoupper</code><code>(</code><code>$product</code><code>));</code>
<code> </code><code>$total</code> <code>+= (</code><code>$priceperitem</code> <code>*</code><code>$quantity</code><code>) * (</code><code>$tax</code> <code>+ 1.0);</code>
<code> </code><code>};</code>
<code> </code><code>array_walk</code><code>(</code><code>$this</code><code>->products,</code><code>$callback</code><code>);</code>
<code> </code><code>return</code> <code>round</code><code>(</code><code>$total</code><code>, 2);;</code>
<code>$my_cart</code> <code>=</code><code>new</code> <code>cart;</code>
<code>// 往購物車裡添加條目</code>
<code>$my_cart</code><code>->add(</code><code>'butter'</code><code>, 1);</code>
<code>$my_cart</code><code>->add(</code><code>'milk'</code><code>, 3);</code>
<code>$my_cart</code><code>->add(</code><code>'eggs'</code><code>, 6);</code>
<code>// 打出出總價格,其中有 5% 的銷售稅.</code>
<code>print</code> <code>$my_cart</code><code>->gettotal(0.05) .</code><code>"\n"</code><code>;</code>
<code>// the result is 54.29</code>
<code>?></code>
這裡如果我們改造gettotal函數必然要使用到foreach
<code>function</code> <code>html (</code><code>$code</code> <code>,</code><code>$id</code><code>=</code><code>""</code><code>,</code><code>$class</code><code>=</code><code>""</code><code>){</code>
<code>if</code> <code>(</code><code>$id</code> <code>!==</code><code>""</code><code>)</code><code>$id</code> <code>=</code><code>" id = \"$id\""</code> <code>;</code>
<code>$class</code> <code>= (</code><code>$class</code> <code>!==</code><code>""</code><code>)?</code><code>" class =\"$class\""</code><code>:</code><code>">"</code><code>;</code>
<code>$open</code> <code>=</code><code>"<$code$id$class"</code><code>;</code>
<code>$close</code> <code>=</code><code>"</$code>"</code><code>;</code>
<code>return</code> <code>function</code> <code>(</code><code>$inner</code> <code>=</code><code>""</code><code>)</code><code>use</code> <code>(</code><code>$open</code><code>,</code><code>$close</code><code>){</code>
<code>return</code> <code>"$open$inner$close"</code><code>;};</code>
<code>如果是使用平時的方法,我們會把inner放到html函數參數中,這樣不管是代碼閱讀還是使用都不如使用閉包</code>
<code> </code><code>$fib</code> <code>=</code><code>function</code><code>(</code><code>$n</code><code>)</code><code>use</code><code>(&</code><code>$fib</code><code>) {</code>
<code> </code><code>if</code><code>(</code><code>$n</code> <code>== 0 ||</code><code>$n</code> <code>== 1)</code><code>return</code> <code>1;</code>
<code> </code><code>return</code> <code>$fib</code><code>(</code><code>$n</code> <code>- 1) +</code><code>$fib</code><code>(</code><code>$n</code> <code>- 2);</code>
<code> </code><code>};</code>
<code> </code><code>echo</code> <code>$fib</code><code>(2) .</code><code>"\n"</code><code>;</code><code>// 2</code>
<code> </code><code>$lie</code> <code>=</code><code>$fib</code><code>;</code>
<code> </code><code>$fib</code> <code>=</code><code>function</code><code>(){</code><code>die</code><code>(</code><code>'error'</code><code>);};</code><code>//rewrite $fib variable</code>
<code> </code><code>echo</code> <code>$lie</code><code>(5);</code><code>// error because $fib is referenced by closure</code>
注意上題中的use使用了&,這裡不使用&會出現錯誤fib(fib(n-1)是找不到function的(前面沒有定義fib的類型)
是以想使用閉包解除循環函數的時候就需要使用
<code>$recursive</code> <code>=</code><code>function</code> <code>()</code><code>use</code> <code>(&</code><code>$recursive</code><code>){</code>
<code>// the function is now available as $recursive</code>
這樣的形式
如果你需要延遲綁定use裡面的變量,你就需要使用引用,否則在定義的時候就會做一份拷貝放到use中
<code>$result</code> <code>= 0;</code>
<code>$one</code> <code>=</code><code>function</code><code>()</code>
<code>{ var_dump(</code><code>$result</code><code>); };</code>
<code>$two</code> <code>=</code><code>function</code><code>()</code><code>use</code> <code>(</code><code>$result</code><code>)</code>
<code>$three</code> <code>=</code><code>function</code><code>()</code><code>use</code> <code>(&</code><code>$result</code><code>)</code>
<code>$result</code><code>++;</code>
<code>$one</code><code>(); </code><code>// outputs null: $result is not in scope</code>
<code>$two</code><code>(); </code><code>// outputs int(0): $result was copied</code>
<code>$three</code><code>(); </code><code>// outputs int(1)</code>
使用引用和不使用引用就代表了是調用時指派,還是申明時候指派