Permalink
Browse files

Implemented filter, fold.

  • Loading branch information...
1 parent 029d979 commit b5f1d43076609578a64e9454cc5593c5252181de @dahlia dahlia committed Nov 27, 2009
Showing with 59 additions and 0 deletions.
  1. +2 −0 Lisphp/Environment.php
  2. +33 −0 Lisphp/Runtime/List.php
  3. +2 −0 Lisphp/Test/EnvironmentTest.php
  4. +22 −0 Lisphp/Test/RuntimeTest.php
View
@@ -26,6 +26,8 @@ static function sandbox() {
$scope['at'] = new Lisphp_Runtime_List_At;
$scope['count'] = new Lisphp_Runtime_List_Count;
$scope['map'] = new Lisphp_Runtime_List_Map;
+ $scope['filter'] = new Lisphp_Runtime_List_Filter;
+ $scope['fold'] = new Lisphp_Runtime_List_Fold;
$scope['=='] = $scope['eq'] = $scope['eq?']
= new Lisphp_Runtime_Predicate_Eq;
$scope['='] = $scope['equal'] = $scope['equal?']
View
@@ -91,3 +91,36 @@ protected function execute(array $arguments) {
}
}
+final class Lisphp_Runtime_List_Filter extends Lisphp_Runtime_BuiltinFunction {
+ protected function execute(array $arguments) {
+ list($predicate, $values) = $arguments;
+ $list = array();
+ foreach ($values as $value) {
+ if (Lisphp_Runtime_Function::call($predicate, array($value))) {
+ $list[] = $value;
+ }
+ }
+ return new Lisphp_List($list);
+ }
+}
+
+final class Lisphp_Runtime_List_Fold extends Lisphp_Runtime_BuiltinFunction {
+ protected function execute(array $arguments) {
+ list($aggregate, $values) = $arguments;
+ if ($hasResult = isset($arguments[2])) {
+ $result = $arguments[2];
+ }
+ foreach ($values as $value) {
+ $result = $hasResult
+ ? Lisphp_Runtime_Function::call($aggregate,
+ array($result, $value))
+ : $value;
+ $hasResult = true;
+ }
+ if ($hasResult) return $result;
+ throw new InvalidArgumentException(
+ 'the initial value or one or more elements of the list are required'
+ );
+ }
+}
+
@@ -32,6 +32,8 @@ function testSandbox($scope = null) {
$this->assertType('Lisphp_Runtime_List_At', $scope['at']);
$this->assertType('Lisphp_Runtime_List_Count', $scope['count']);
$this->assertType('Lisphp_Runtime_List_Map', $scope['map']);
+ $this->assertType('Lisphp_Runtime_List_Filter', $scope['filter']);
+ $this->assertType('Lisphp_Runtime_List_Fold', $scope['fold']);
$this->assertType('Lisphp_Runtime_Predicate_Eq', $scope['==']);
$this->assertType('Lisphp_Runtime_Predicate_Eq', $scope['eq']);
$this->assertType('Lisphp_Runtime_Predicate_Eq', $scope['eq?']);
@@ -609,6 +609,28 @@ function testMap() {
}
}
+ function testFilter() {
+ $filter = new Lisphp_Runtime_List_Filter;
+ $this->assertFunction(new Lisphp_List(array(1, 3, 5)),
+ $filter,
+ new Lisphp_Runtime_Predicate_Type('int'),
+ array(1, '2', 3, array(4), 5));
+ }
+
+ function testFoldl() {
+ $fold = new Lisphp_Runtime_List_Fold;
+ $agg = new Lisphp_Runtime_Arithmetic_Subtraction;
+ $this->assertFunction(3, $fold, $agg, array(25, 9, 5, 7, 1));
+ $this->assertFunction(3, $fold, $agg, array(9, 5, 7, 1), 25);
+ $this->assertFunction(25, $fold, $agg, array(), 25);
+ try {
+ $this->applyFunction($fold, $agg, array());
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ # pass.
+ }
+ }
+
function methodTest($a) {
return array($this, $a);
}

0 comments on commit b5f1d43

Please sign in to comment.