Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
добавлен "Список"
  • Loading branch information
LionsHead committed Mar 6, 2016
commit 8d9fc22f71a63ef25b86ea31d9112de149dd6764
108 changes: 108 additions & 0 deletions src/Lists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace Lists;
use function Pairs\cons;
use function Pairs\car;
use function Pairs\cdr;
use function Pairs\toString;


/**
* применяет callable-функцию $func к списку $list
* @method map
* @param callable $func функция
* @param callable $list список
* @return [type] [description]
*/
function map(callable $func, callable $list) {
$map = function ($items, $acc) use (&$map, $func) {
if (is_null($items)) {
return reverse($acc);
}
return $map(cdr($items), cons($func(car($items)), $acc));
};

return $map($list, null);
}

/**
* фильтрует список с помощью callable-функции
* @method filter
* @param callable $func функция
* @param callable $list список
* @return [type] [description]
*/
function filter(callable $func, callable $list) {
$map = function ($func, $items) use (&$map) {
if ($items === null) {
return null;
} else {
$curr = car($items);
$rest = $map($func, cdr($items));
// filter
return $func($curr) ? cons($curr, $rest) : $rest;
}
};

return $map($func, $list);
}

/**
* сворачивает список с помощью callable-функции
* @method reduce
* @param callable $func функция
* @param callable $list список
* @param mixed $acc
* @return [type] [description]
*/
function reduce(callable $func, callable $list, $acc = null) {
$iter = function ($items, $acc) use (&$iter, $func) {
return is_null($items) ? $acc : $iter(cdr($items), $func(car($items), $acc));
};

return $iter($list, $acc);
}

/**
* соединяет два списка
* @method append
* @param pair $list1
* @param pair $list2
* @return новый список
*/
function append(callable $list1, callable $list2)
{
if ($list1 === null) {
return $list2;
} else {
return cons(car($list1), append(cdr($list1), $list2));
}
}

/**
* переворачивает список
* @method reverse
* @param callable $list список
* @return перевернутый список
*/
function reverse(callable $list) {
$iter = function ($items, $acc) use (&$iter) {
return is_null($items) ? $acc : $iter(cdr($items), cons(car($items), $acc));
};

return $iter($list, null);
}

/**
* возвращает длинну списка
* @method length
* @param callable $list список
* @return integer длинна списка
*/
function length($list) {
if ($list === null || !is_callable($list)) {
return 0;
} else {
return 1 + length(cdr($list));
}
}
2 changes: 1 addition & 1 deletion src/Pairs.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function toString($list)
$arr = [];
$iter = function ($items) use (&$arr, &$iter) {
if ($items != null) {
$arr[] = listToString(car($items));
$arr[] = toString(car($items));
$iter(cdr($items));
}

Expand Down
72 changes: 72 additions & 0 deletions tests/ListsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Pairs\tests;


use function Pairs\cons;
use function Pairs\car;
use function Pairs\cdr;
use function Pairs\toString;


use function Lists\length;
use function Lists\reverse;
use function Lists\map;
use function Lists\filter;
use function Lists\reduce;

class ListsTest extends \PHPUnit_Framework_TestCase
{
public function testPairs()
{
$pair = cons(1, 2);
$this->assertEquals(1, car($pair));
$this->assertEquals(2, cdr($pair));
}

public function testLength()
{
$list = cons(1,cons(2, cons(3, null)));
$this->assertEquals(3, length($list));

}

public function testReverse()
{
$list = cons(1, cons(2, cons(3, null)));
$expected = toString(cons(3, cons(2, cons(1, null))));
$this->assertEquals($expected, toString(reverse($list)));
}

public function testMap()
{
$list = cons(1, cons(2, cons(3, null)));
$expected = toString(cons(3, cons(4, cons(5, null))));
$map = map(function ($x) {
return $x + 2;
}, $list);
$this->assertEquals($expected, toString($map));
}

public function testFilter()
{
$list = cons(2, cons(3, cons(4, null)));
$expected = toString(cons(2, cons(4, null)));
$filter = filter(function ($x) {
return $x % 2 == 0;
}, $list);

$this->assertEquals(2, length($filter));
$this->assertEquals($expected, toString($filter));
}

public function testReduce()
{
$list = cons(1, cons(2, cons(3, null)));
$expected = 6;
$map = reduce(function ($x, $acc) {
return $x + $acc;
}, $list, 0);
$this->assertEquals($expected, $map);
}
}
2 changes: 0 additions & 2 deletions tests/PairsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Pairs\tests;

require_once 'Pairs.php';

use function Pairs\cons;
use function Pairs\car;
use function Pairs\cdr;
Expand Down