Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,39 @@
[![Build Status](https://travis-ci.org/hexlet-components/php-pairs.svg?branch=master)](https://travis-ci.org/hexlet-components/php-pairs)
[![Code Climate](https://codeclimate.com/github/hexlet-components/php-pairs/badges/gpa.svg)](https://codeclimate.com/github/hexlet-components/php-pairs)
[![Issue Count](https://codeclimate.com/github/hexlet-components/php-pairs/badges/issue_count.svg)](https://codeclimate.com/github/hexlet-components/php-pairs)


### Functions for working with Pairs
```
use function Pairs\cons;
use function Pairs\car;
use function Pairs\cdr;
use function Pairs\toString;
```

### Functions for working with Lists
```
use function Lists\length;
use function Lists\reverse;
use function Lists\map;
use function Lists\filter;
use function Lists\reduce;
```
### example
\# 1
```
$pair = cons(1, 2);

$one = Pairs\car($pair); // $one = 1;
$two = Pairs\cdr($pair) // $two = 2;
```
\# 2
```
$list = cons(1, cons(2, cons(3, cons(4, cons(5, cons(6, null))))));
$length = length($list); // $length = 6;

$filter = filter(function ($x) {
return $x % 2 == 0;
}, $list);
$result = toString($filter); \\ $result = "(2, 4, 6)";
```
39 changes: 20 additions & 19 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
{
"name": "hexlet\\pairs",
"description": "",
"license": "MIT",
"keywords": ["pairs"],
"authors": [
{
"name": "Kirill Mokevnin",
"email": "[email protected]"
"name": "hexlet\\pairs",
"description": "",
"license": "MIT",
"keywords": ["pairs"],
"authors": [
{
"name": "Kirill Mokevnin",
"email": "[email protected]"
}
],
"require": {},
"require-dev": {
"phpunit/phpunit": "*",
"squizlabs/php_codesniffer": "2.*"
},
"autoload": {
"files": [
"src/Pairs.php",
"src/Lists.php"
]
}
],
"require": {},
"require-dev": {
"phpunit/phpunit": "*",
"squizlabs/php_codesniffer": "2.*"
},
"autoload": {
"files": [
"src/Pairs.php"
]
}
}
19 changes: 19 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
107 changes: 107 additions & 0 deletions src/Lists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Lists;

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

/**
* Applies callable function $func to list $list
* @param callable $func function
* @param callable $list list
* @return result list
*/
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);
}

/**
* Filters list $list using callable function $func
* @param callable $func function
* @param callable $list list
* @return result list
*/
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);
}

/**
* Collapses the list $list using callable function $func
* @param callable $func function
* @param callable $list list
* @param mixed $acc
* @return result
*/
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);
}

/**
* Concatenates two lists
* @param pair $list1
* @param pair $list2
* @return new list
*/
function append(callable $list1, callable $list2)
{
if ($list1 === null) {
return $list2;
} else {
return cons(car($list1), append(cdr($list1), $list2));
}
}

/**
* Reverse list $list
* @param callable $list list
* @return result
*/
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);
}

/**
* Returns length of list
* @param callable $list list
* @return integer length
*/
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
62 changes: 62 additions & 0 deletions tests/ListsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?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 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);
}
}