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
8 changes: 6 additions & 2 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
name: bingo-functional CI
on: [push, pull_request]
on:
push:
branches:
- v1.x
- v2.x
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
name: PHP ${{ matrix.php }}
steps:
- uses: actions/checkout@v3
Expand Down
27 changes: 27 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# bingo-functional changes

## v2.5.0

- Added `Chemem\Bingo\Functional\listFromPaths`
- Added nullable type definitions to arguments in the following functions
- `Chemem\Bingo\Functional\paths`
- `Chemem\Bingo\Functional\toException`
- `Chemem\Bingo\Functional\Functors\Monads\bind`
- Reworked the internals of the following functions
- `Chemem\Bingo\Functional\memoize`
- `Chemem\Bingo\Functional\head`
- `Chemem\Bingo\Functional\last`
- `Chemem\Bingo\Functional\indexOf`
- `Chemem\Bingo\Functional\intersects`
- `Chemem\Bingo\Functional\isArrayOf`
- `Chemem\Bingo\Functional\omit`
- `Chemem\Bingo\Functional\where`
- `Chemem\Bingo\Functional\keysExist`
- `Chemem\Bingo\Functional\any`
- `Chemem\Bingo\Functional\assocPath`
- `Chemem\Bingo\Functional\every`
- `Chemem\Bingo\Functional\fromPairs`
- `Chemem\Bingo\Functional\has`
- `Chemem\Bingo\Functional\tail`
- Improved iteration patterns in functions subsumed in the following classes
- `Chemem\Bingo\Functional\Immutable\Collection`
- `Chemem\Bingo\Functional\Immutable\Tuple`

## v2.4.0

- Added `jsonDecode` and `extract` functions
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
}
],
"require": {
"php": "^7 || ^8"
"php": "^7.2 || ^8"
},
"require-dev": {
"ergebnis/composer-normalize": "^2",
Expand Down
19 changes: 9 additions & 10 deletions src/Functional/Any.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
*/
function any($list, callable $func): bool
{
return fold(
function (bool $valid, $entry) use ($func) {
if ($func($entry)) {
return true;
}
$valid = false;

return $valid;
},
$list,
false
);
foreach ($list as $value) {
if ($func($value)) {
$valid = true;
break;
}
}

return $valid;
}
34 changes: 24 additions & 10 deletions src/Functional/ArrayKeysExist.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,31 @@ function arrayKeysExist(array $list, ...$keys): bool
*/
function keysExist($list, ...$keys): bool
{
$check = fold(
function ($acc, $val, $idx) use ($keys) {
if (\in_array($idx, $keys)) {
$acc[] = $val;
$exist = false;
$matches = 0;
$idx = 0;

while (isset($keys[$idx])) {
$next = $keys[$idx];

if (\is_object($list)) {
if (isset($list->{$next})) {
$matches += 1;
}
}

if (\is_array($list)) {
if (isset($list[$next])) {
$matches += 1;
}
}

if (!isset($keys[$idx + 1]) && equals($matches, $idx + 1)) {
$exist = true;
}

return $acc;
},
$list,
[]
);
$idx++;
}

return equals(size($check), size($keys));
return $exist;
}
86 changes: 18 additions & 68 deletions src/Functional/AssocPath.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
namespace Chemem\Bingo\Functional;

require_once __DIR__ . '/Internal/_JsonPath.php';
require_once __DIR__ . '/Internal/_MergeN.php';

use function Chemem\Bingo\Functional\Internal\_jsonPath;
use function Chemem\Bingo\Functional\Internal\_mergeN;

const assocPath = __NAMESPACE__ . '\\assocPath';

Expand All @@ -36,78 +34,30 @@
*/
function assocPath($path, $val, $list)
{
$path = _jsonPath($path);
$keys = _jsonPath($path);
$tmp = &$list;
$idx = 0;

if (!\is_null(pluckPath($path, $list))) {
$pathc = size($path);
while ($keys) {
$key = \array_shift($keys);

if (equals($pathc, 0)) {
return $list;
}

$idx = head($path);

if ($pathc > 1) {
$next = pluck($list, $idx);

if (\is_object($next) || \is_array($next)) {
$val = assocPath(dropLeft($path), $val, $next);
if (\is_array($list)) {
if (!\is_array($tmp)) {
$tmp = [];
}
}

return assoc($idx, $val, $list);
} else {
$listc = size($list);
$lcheck = pluckPath(dropRight($path, 1), $list);
$clone = function ($path, $val, $list) use (
&$clone,
$listc,
$lcheck
) {
return fold(
function ($acc, $entry) use (
&$clone,
$lcheck,
$list,
$listc,
$path,
$val
) {
if (equals(size($acc), 1)) {
// preempt extraneous list concatenation
return $acc;
}

if (equals(size($path), 1)) {
// check if the key exists
if (!\is_null($lcheck)) {
if (\is_array($lcheck)) {
$lcheck[$entry] = $val;
} elseif (\is_object($lcheck)) {
$lcheck->{$entry} = $val;
}

$acc = (array) $lcheck;
} else {
$acc[$entry] = $val;
}

$acc[$entry] = $val;
} else {
$acc[$entry] = $clone(dropLeft($path), $val, $list);
}

return $acc;
},
$path,
[]
);
};

$result = $clone($path, $val, $list);
$tmp = &$tmp[$key];
} elseif (\is_object($list)) {
if (!\is_object($tmp)) {
$tmp = (new \ReflectionClass($list))
->newInstanceWithoutConstructor();
}

return _mergeN($list, $result);
$tmp = &$tmp->{$key};
}
}

$tmp = $val;

return $list;
}
20 changes: 8 additions & 12 deletions src/Functional/Every.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,14 @@
*/
function every($list, callable $func): bool
{
[$filterCount, $valCount] = fold(
function ($acc, $val) use ($func) {
[$fst, $snd] = $acc;
$fst = $fst + 1;
$valid = true;

$snd += $func($val) ? 1 : 0;
foreach ($list as $value) {
if (equals($func($value), false)) {
$valid = false;
break;
}
}

return [$fst, $snd];
},
$list,
[0, 0]
);

return equals($filterCount, $valCount);
return $valid;
}
27 changes: 20 additions & 7 deletions src/Functional/FromPairs.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,26 @@ function fromPairs($list)
{
return fold(
function ($acc, $val, $key) {
if (equals(size($val), 2)) {
if (\is_object($acc)) {
$acc->{head($val)} = last($val);
unset($acc->{$key});
} elseif (\is_array($acc)) {
$acc[head($val)] = last($val);
unset($acc[$key]);
if (\is_array($val) || \is_object($val)) {
$list = [];

foreach ($val as $entry) {
$list[] = $entry;

if (equals(++$count, 2)) {
$idx = pluck($list, 0);
$next = pluck($list, 1);

if (\is_object($acc)) {
$acc->{$idx} = $next;
unset($acc->{$key});
} elseif (\is_array($acc)) {
$acc[$idx] = $next;
unset($acc[$key]);
}

break;
}
}
}

Expand Down
25 changes: 12 additions & 13 deletions src/Functional/Has.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@
*/
function has($haystack, $needle): bool
{
return fold(
function (bool $exists, $entry) use ($needle) {
if (equals($needle, $entry, true)) {
return true;
}
$exists = false;

if (\is_object($entry) || \is_array($entry)) {
$exists = has($entry, $needle);
}
foreach ($haystack as $entry) {
if (equals($needle, $entry, true)) {
$exists = true;
break;
}

return $exists;
},
$haystack,
false
);
if (\is_object($entry) || \is_array($entry)) {
$exists = has($entry, $needle);
}
}

return $exists;
}
30 changes: 16 additions & 14 deletions src/Functional/Head.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,32 @@
* head
* Outputs the first element in a list
*
* head :: [a] -> a
* head :: [a] -> a -> a
*
* @param object|array $list
* @param mixed $default
* @return mixed
* @example
*
* head(range(4, 7))
* => 4
*/
function head($list, $def = null)
function head($list, $default = null)
{
$count = 0;

foreach ($list as $val) {
if (equals($count, 0)) {
return $val;
}
if (
!(
\is_object($list) ||
\is_array($list)
)
) {
return $default;
}

if ($count > 0) {
break;
}
\reset($list);

$count += 1;
}
$result = \current($list);

return $def;
return equals($result, false) ?
$default :
$result;
}
Loading