【问题标题】:php advanced functional programming - creating a curry method similar to ramdaJSphp高级函数式编程——创建类似于ramdaJS的curry方法
【发布时间】:2015-10-04 13:25:24
【问题描述】:

要求:

  1. 占位符支持
  2. 部分应用函数可以应用于部分应用函数
  3. 咖喱
  4. 5.6 PHP 支持

这是我的尝试,但它只支持 hhvm 3.7,正如您在 http://3v4l.org/0i5FV 上的示例中看到的那样

<?php 
class Placeholder{}
function curry(callable $func, ... $curriedArgs) {
    return function(...$fulfillment) use ($func, $curriedArgs) {
        $removedPlaceheldArgs = array_map(function($arg) use ($fulfillment) {
            if ($arg instanceof Placeholder)
                return array_shift($fulfillment);
            return $arg;
        }, $curriedArgs);
        return $func(...array_merge($removedPlaceheldArgs, $fulfillment));
    };
};

这是我的用法示例:

$resultset = json_decode('[{
  "id": 1,
  "gender": "Male",
  "name": "Matthew"
}, {
  "id": 2,
  "gender": "Male",
  "name": "Willie"
}, {
  "id": 3,
  "gender": "Female",
  "name": "Ann"
}, {
  "id": 4,
  "gender": "Female",
  "name": "Margaret"
}, {
  "id": 5,
  "gender": "Female",
  "name": "Marie"
}]',TRUE);

$filterGender = function($row,$gender){
    return $row['gender']==$gender;
};

$detectMen = curry($filterGender,(new Placeholder),'Male');
$detectWomen = curry($filterGender,(new Placeholder),'Female');

var_dump($detectMen(['gender'=>'Male'])); //works -- expected result TRUE

$getLadies = curry('array_filter',(new Placeholder),$detectWomen);

var_dump($getLadies($resultset)); //does not work -- expected result Ladies from result set

可以在 PHP 5.6 中实现 $getLadies 结果而不仅仅是 hhvm 吗?

【问题讨论】:

    标签: php functional-programming currying partial-application ramda.js


    【解决方案1】:

    您可以使用来自Non-standard PHP librarypartial applicationcurry 函数:

    use function nspl\f\rpartial;
    
    $detectMen = rpartial($filterGender, 'Male');
    $detectWomen = rpartial($filterGender, 'Female');
    
    var_dump($detectMen(array('gender' => 'Male')));
    
    $getLadies = rpartial('array_filter', $detectWomen);
    
    var_dump($getLadies($resultset));
    

    【讨论】:

      【解决方案2】:

      它并不漂亮,但这应该是对 Ramda 当前curry 函数的近似模拟。

      namespace Phamda {
          function _() {
              static $placeholder;
              if ($placeholder === null) {
                  $placeholder = new \stdClass;
              }
              return $placeholder;
          }
      
          function curryN($n, $f) {
              $curryNRec = function($recv) use ($n, $f, &$curryNRec) {
                  return function () use ($recv, $n, $f, &$curryNRec) {
                      $left = $n;
                      $argsIdx = 0;
                      $combined = array();
                      $combindedIdx = 0;
                      $args = func_get_args();
                      while ($combindedIdx < count($recv) || $argsIdx < count($args)) {
                          if ($combindedIdx < count($recv)
                              && ($recv[$combindedIdx] !== _() || $argsIdx > count($args))) {
                              $result = $recv[$combindedIdx];
                          } else {
                              $result = $args[$argsIdx];
                              $argsIdx += 1;
                          }
                          $combined[$combindedIdx] = $result;
                          $combindedIdx += 1;
                          if ($result !== _()) {
                              $left -= 1;
                          }
                      }
                      if ($left <= 0) {
                          return call_user_func_array($f, $combined);
                      } else {
                          return $curryNRec($combined);
                      }
                  };
              };
              return $curryNRec([]);
          }
      
          function curry($f) {
              $fRefl = new \ReflectionFunction($f);
              return curryN($fRefl->getNumberOfParameters(), $f);
          }
      }
      

      并使用您的示例:

      use Phamda as P;
      
      $resultset = json_decode('[{
        "id": 1,
        "gender": "Male",
        "name": "Matthew"
      }, {
        "id": 2,
        "gender": "Male",
        "name": "Willie"
      }, {
        "id": 3,
        "gender": "Female",
        "name": "Ann"
      }, {
        "id": 4,
        "gender": "Female",
        "name": "Margaret"
      }, {
        "id": 5,
        "gender": "Female",
        "name": "Marie"
      }]', true);
      
      $filterGender = P\curry(function($row, $gender){
          return $row['gender'] == $gender;
      });
      
      $detectMen = $filterGender(P\_(), 'Male');
      $detectWomen = $filterGender(P\_(), 'Female');
      
      var_dump($detectMen(['gender' => 'Male']));
      // bool(true)
      
      $filter = P\curry('array_filter');
      $getLadies = $filter(P\_(), $detectWomen);
      
      var_dump($getLadies($resultset));
      /*
      array(3) {
        [2] =>
        array(3) {
          'id' =>
          int(3)
          'gender' =>
          string(6) "Female"
          'name' =>
          string(3) "Ann"
        }
        [3] =>
        array(3) {
          'id' =>
          int(4)
          'gender' =>
          string(6) "Female"
          'name' =>
          string(8) "Margaret"
        }
        [4] =>
        array(3) {
          'id' =>
          int(5)
          'gender' =>
          string(6) "Female"
          'name' =>
          string(5) "Marie"
        }
      }
      */
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-09
        • 1970-01-01
        • 2022-01-10
        • 2021-07-12
        • 2023-03-03
        • 2010-10-11
        • 1970-01-01
        相关资源
        最近更新 更多