2010-07-25 35 views
5

Tôi có thể sử dụng PHP 5.3 Closures như thế nào Chúng tôi sử dụng các khối trong Ruby. Tôi không bao giờ sử dụng 'for' Loop trong Ruby do sử dụng Blocks với 'each' 'find_all' 'inject' Methods.Tôi có thể sử dụng PHP 5.3 Closures như thế nào Chúng tôi sử dụng các khối trong Ruby

Làm thế nào tôi có thể sử dụng PHP 5.3 đóng cửa như Ruby Blocks và nói bye-bye để 'cho' Loops :)

Giống như giữa {và} là một Đóng (hoặc Chặn hoặc Anonymous Function)

fruit = %w[apple banana orange] 
fruit.each { |f| print "#{f}, " } 

tôi làm điều đó trong PHP theo cách này,

$fruit = array('apple', 'banana', 'orange'); 
foreach ($fruit as $f) 
{ 
print "$f, "; 
} 

có cách nào để làm điều này Ruby cách sử dụng đóng cửa PHP như PHP 5.3 hỗ trợ nó.

+0

Bạn không thể dạy các thủ thuật mới cho chó cũ. PHP có tất cả các tính năng "ưa thích" (OO, không gian tên, bao đóng) theo thời gian, nhưng nó chưa được thiết kế chính xác ngay từ đầu - nghĩa là tất cả các tính năng ngôn ngữ hiện có, nhưng không phải lúc nào cũng hữu ích và tiện lợi sử dụng. Như bạn có thể thấy từ các câu trả lời, nó vẫn là dễ nhất và thanh lịch nhất để sử dụng các hàm mảng được xác định trước. –

+0

Ồ, một điều quan trọng khác: đóng cửa không giống như các hàm ẩn danh. Đóng cửa cần phải giữ môi trường chúng được xác định trong, để gọi chúng là đóng cửa.Các chức năng ẩn danh không cần. Và, về mặt kỹ thuật, các khối Ruby không hoạt động, chúng là một cấu trúc ngôn ngữ. Nhưng chúng có thể dễ dàng được chuyển đổi thành các hàm, bằng cách thêm chúng với 'lambda', chẳng hạn. –

+0

Rohit, bạn có thể giải thích lý do tại sao các lập trình viên Ruby không thích "cho" vòng lặp? Dường như với tôi hầu hết thời gian họ đang sử dụng một khối nó để làm điều tương tự như một "cho" vòng lặp (hoặc "foreach" trong php) nhưng họ dường như thực sự ghét họ. Tôi đã hỏi trước và chưa bao giờ nhận được câu trả lời hay. – James

Trả lời

5

Nếu bạn đang xem xét sử dụng lambdas để lặp qua một mảng PHP, có một số chức năng mà bạn có thể sử dụng để thực hiện điều đó. Better minh họa nó, tôi đã sử dụng một lớp wrapper enum:

class enum { 
    public $arr; 

    function __construct($array) { 
     $this->arr = $array; 
    } 

    function each($lambda) { 
     array_walk($this->arr, $lambda); 
    } 

    function find_all($lambda) { 
     return array_filter($this->arr, $lambda); 
    } 

    function inject($lambda, $initial=null) { 
     if ($initial == null) { 
      $first = array_shift($this->arr); 
      $result = array_reduce($this->arr, $lambda, $first); 
      array_unshift($this->arr, $first); 

      return $result; 
     } else { 
      return array_reduce($this->arr, $lambda, $initial); 
     } 
    } 

} 


$list = new enum(array(-1, 3, 4, 5, -7)); 
$list->each(function($a) { print $a . "\n";}); 

// in PHP you can also assign a closure to a variable 
$pos = function($a) { return ($a < 0) ? false : true;}; 
$positives = $list->find_all($pos); 

// inject() examples 
$list = new enum(range(5, 10)); 

$sum = $list->inject(function($sum, $n) { return $sum+$n; }); 
$product = $list->inject(function($acc, $n) { return $acc*$n; }, 1); 

$list = new enum(array('cat', 'sheep', 'bear')); 
$longest = $list->inject(function($memo, $word) { 
     return (strlen($memo) > strlen($word)) ? $memo : $word; } 
    ); 

Điều đó đang được nói, đóng cửa trong PHP không có nghĩa là để thay thế cho vòng lặp cũng không làm họ cư xử như khối ruby.

+0

Cảm ơn, tôi nghĩ array_map() và array_walk() trông tốt hơn cho mục đích này –

+0

@Rohit Vâng, tôi chỉ muốn làm cho nó dễ dàng hơn cho bạn liên quan đến ruby. Bằng cách này tôi đã thêm phương thức 'inject()'. – quantumSoup

0

Tôi không nghĩ rằng một hàm ẩn danh là một thay thế cho vòng lặp for, cũng như tôi nghĩ rằng nó cần thiết để thay thế cho các vòng lặp với chúng.

Điều gì hữu ích cho việc gọi lại. Thực hiện việc này ví dụ: (vâng, nó là một loại bong bóng què, nhưng nó là một ví dụ)

<?php 

function bubble_sort($sort_rule, $elements) { 
    do { 
     $swapped = false; 
     for ($i = 0; $i < count($elements) - 1; $i++) { 
      if ($sort_rule($elements[$i], $elements[$i + 1])) { 
       $elements[$i] ^= $elements[$i + 1]; 
       $elements[$i + 1] ^= $elements[$i]; 
       $elements[$i] ^= $elements[$i + 1]; 
       $swapped = true; 
      } 
     } 
    } while($swapped); 
    return $elements; 
} 

print_r(bubble_sort(function ($a, $b) { if ($a > $b) return true; else return false; } 
,array(1,6,3,7,42,-1,0,6))); 
?> 

đóng cửa không phải là một sự thay thế cho cho vòng bằng một ngôn ngữ lập trình thủ tục như php. Chắc chắn nếu bạn đang sử dụng lisp hoặc đề án họ đang có, nhưng đó là sự cần thiết.

Bạn có thể viết theo cách đó, tất cả những gì bạn thực sự sẽ làm là tạo ra một hàm ẩn danh với vòng lặp for bên trong nó. Tôi nghĩ rằng đệ quy sẽ chỉ là không cần thiết nếu nhiệm vụ chỉ là dễ dàng thực hiện với một vòng lặp for, và do đó bạn không hôn nhau cho các vòng tạm biệt.

Chức năng ẩn danh rất hữu ích trong lập trình hướng sự kiện, khi bạn muốn xác định phương thức gọi lại rất nhanh.

+0

Trong ngôn ngữ Clojure (được phát triển từ sơ đồ), nó có vẻ như đang sử dụng các bao đóng thay cho các vòng 'for'. Tôi nghĩ rằng trong PHP của nó không thể :) Cảm ơn rất nhiều –

0

Câu trả lời đơn giản: bạn không thích. Ruby không phải là dành cho() vòng lặp, họ chỉ cần mặt nạ từ "cho" và thay đổi cú pháp một chút. Nếu bạn muốn sử dụng một đóng cửa, nó sẽ chỉ là một đóng cửa với một vòng lặp bên trong nó, hoặc một đóng cửa đệ quy xấu xí (và kém hiệu quả).

Và đóng cửa KHÔNG giống như các khối. Các đóng có thể so sánh được với các hàm trong JavaScript-- nghĩa là chúng có thể được lưu trữ trong các biến và được gửi dưới dạng đối số.

+0

Cảm ơn có Tôi nghĩ rằng bạn là chính xác, đóng cửa và khối khác nhau theo nhiều cách –

+1

1. Ruby _is_ không có 'for' vòng (cú pháp,' for' tồn tại, nhưng khối hoàn toàn làm cho nó thừa, không phải bằng cách "thay đổi cú pháp một chút", nhưng là tính năng ngôn ngữ hữu ích và phổ biến). 2. Ruby chặn _are_ đóng cửa. Chúng có thể được lưu trữ trong các biến và được gửi dưới dạng đối số. –

2

Tôi nghĩ array_map() và array_walk() trông đẹp hơn khi thay thế RubyBlocks.

Các vấn đề liên quan