Skip to content

Commit

Permalink
refactor: Leverage tacit programming (point free style)
Browse files Browse the repository at this point in the history
Point free style operation to avoid repeating closures that are already
existing in Compose operation.
  • Loading branch information
drupol committed Sep 24, 2020
1 parent 675af9a commit 13b5d6d
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 124 deletions.
26 changes: 12 additions & 14 deletions src/Operation/Flatten.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,21 @@ static function (Iterator $iterator) use ($depth): Generator {
foreach ($iterator as $key => $value) {
if (false === is_iterable($value)) {
yield $key => $value;
} elseif (1 === $depth) {
/** @psalm-var TKey $subKey */
/** @psalm-var T $subValue */
foreach ($value as $subKey => $subValue) {
yield $subKey => $subValue;
}
} else {

continue;
}

if (1 !== $depth) {
/** @psalm-var callable(Iterator<TKey, T>): Generator<TKey, T> $flatten */
$flatten = Flatten::of()($depth - 1);

/**
* @psalm-var TKey $subKey
* @psalm-var T $subValue
*/
foreach ($flatten(new IterableIterator($value)) as $subKey => $subValue) {
yield $subKey => $subValue;
}
$value = $flatten(new IterableIterator($value));
}

/** @psalm-var TKey $subKey */
/** @psalm-var T $subValue */
foreach ($value as $subKey => $subValue) {
yield $subKey => $subValue;
}
}
};
Expand Down
55 changes: 29 additions & 26 deletions src/Operation/Frequency.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,45 @@ final class Frequency extends AbstractOperation
*/
public function __invoke(): Closure
{
return
$reduceCallback =
/**
* @psalm-param Iterator<TKey, T> $iterator
* @psalm-param array<int, array{0: int, 1: T}> $storage
* @psalm-param T $value
*
* @psalm-return Generator<int, T>
* @psalm-return array<int, array{0: int, 1: T}>
*
* @param mixed $value
*/
static function (Iterator $iterator): Generator {
$storage = [];

foreach ($iterator as $value) {
$added = false;

foreach ($storage as $key => $data) {
if ($data['value'] !== $value) {
continue;
}

++$storage[$key]['count'];
$added = true;

break;
}
static function (array $storage, $value): array {
$added = false;

if (false !== $added) {
foreach ($storage as $key => $data) {
if ($data[1] !== $value) {
continue;
}

$storage[] = [
'value' => $value,
'count' => 1,
];
++$storage[$key][0];
$added = true;

break;
}

foreach ($storage as $value) {
yield $value['count'] => $value['value'];
if (false !== $added) {
return $storage;
}

$storage[] = [1, $value];

return $storage;
};

/** @psalm-var Closure(Iterator<TKey, T>): Generator<int, T> $compose */
$compose = Compose::of()(
FoldLeft::of()($reduceCallback)([]),
Flatten::of()(1),
Unpack::of()
);

return $compose;
}
}
14 changes: 5 additions & 9 deletions src/Operation/Head.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,10 @@ final class Head extends AbstractOperation
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<TKey, T>
*/
static function (Iterator $iterator): Generator {
return yield $iterator->key() => $iterator->current();
};
/** @psalm-var Closure(Iterator<TKey, T>): Generator<TKey, T> $first */
$first = First::of();

// Point free style.
return $first;
}
}
1 change: 1 addition & 0 deletions src/Operation/Intersect.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static function ($value, $key, Iterator $iterator) use ($values): bool {
/** @psalm-var Closure(Iterator<TKey, T>): Generator<TKey, T> $filter */
$filter = Filter::of()($filterCallbackFactory($values));

// Point free style.
return $filter;
};
}
Expand Down
20 changes: 8 additions & 12 deletions src/Operation/Pack.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,27 @@
final class Pack extends AbstractOperation
{
/**
* @psalm-return Closure(Iterator<TKey, T>): Generator<int, array{0:TKey, 1:T}>
* @psalm-return Closure(Iterator<TKey, T>): Generator<int, array{0: TKey, 1: T}>
*/
public function __invoke(): Closure
{
$callbackForKeys = static function (): void {
};
$callbackForValues =
$mapCallback =
/**
* @psalm-param T $initial
* @psalm-param TKey $key
* @psalm-param T $value
* @psalm-param TKey $key
*
* @psalm-return array{0: TKey, 1: T}
*
* @param mixed $initial
* @param mixed $key
* @param mixed $value
* @param mixed $key
*
* @psalm-return array{0: TKey, 1: T}
*/
static function ($initial, $key, $value): array {
static function ($value, $key): array {
return [$key, $value];
};

/** @psalm-var Closure(Iterator<TKey, T>): Generator<int, array{0: TKey, 1: T}> $compose */
$compose = Compose::of()(
Associate::of()($callbackForKeys)($callbackForValues),
Map::of()($mapCallback),
Normalize::of()
);

Expand Down
72 changes: 37 additions & 35 deletions src/Operation/Since.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
*/
final class Since extends AbstractOperation
{
Expand All @@ -28,45 +30,45 @@ public function __invoke(): Closure
*/
static function (callable ...$callbacks): Closure {
return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<TKey, T>
*/
static function (Iterator $iterator) use ($callbacks): Generator {
$reducer =
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Closure(bool, callable(T, TKey): bool): bool
*/
static function (Iterator $iterator): Closure {
return
/**
* @psalm-param bool $carry
* @psalm-param callable(T, TKey): bool $callback
*/
static function (bool $carry, callable $callback) use ($iterator): bool {
return ($callback($iterator->current(), $iterator->key())) ?
$carry :
false;
};
};
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<TKey, T>
*/
static function (Iterator $iterator) use ($callbacks): Generator {
$reducer =
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Closure(bool, callable(T, TKey): bool): bool
*/
static function (Iterator $iterator): Closure {
return
/**
* @psalm-param bool $carry
* @psalm-param callable(T, TKey): bool $callback
*/
static function (bool $carry, callable $callback) use ($iterator): bool {
return ($callback($iterator->current(), $iterator->key())) ?
$carry :
false;
};
};

while ($iterator->valid()) {
$result = array_reduce($callbacks, $reducer($iterator), true);
while ($iterator->valid()) {
$result = array_reduce($callbacks, $reducer($iterator), true);

if (false !== $result) {
break;
}
if (false !== $result) {
break;
}

$iterator->next();
}
$iterator->next();
}

for (; $iterator->valid(); $iterator->next()) {
yield $iterator->key() => $iterator->current();
}
};
for (; $iterator->valid(); $iterator->next()) {
yield $iterator->key() => $iterator->current();
}
};
};
}
}
8 changes: 3 additions & 5 deletions src/Operation/Unwrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ final class Unwrap extends AbstractOperation
*/
public function __invoke(): Closure
{
/** @psalm-var Closure(Iterator<TKey, array<TKey, T>>): Generator<TKey, T> $compose */
$compose = Compose::of()(
Flatten::of()(1)
);
/** @psalm-var Closure(Iterator<TKey, array<TKey, T>>): Generator<TKey, T> $flatten */
$flatten = Flatten::of()(1);

// Point free style.
return $compose;
return $flatten;
}
}
30 changes: 18 additions & 12 deletions src/Operation/Unzip.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
*/
final class Unzip extends AbstractOperation
{
Expand All @@ -20,25 +22,29 @@ final class Unzip extends AbstractOperation
*/
public function __invoke(): Closure
{
return
$reduceCallback =
/**
* @psalm-param Iterator<TKey, list<T>> $iterator
* @psalm-param array<int, list<T>> $carry
* @psalm-param iterable<TKey, T> $value
*
* @psalm-return Generator<int, list<T>>
* @psalm-return array<int, list<T>>
*/
static function (Iterator $iterator): Generator {
static function (array $carry, iterable $value): array {
$index = 0;
$result = [];

foreach ($iterator as $current) {
foreach ($current as $c) {
$result[$index++][] = $c;
}

$index = 0;
foreach ($value as $v) {
$carry[$index++][] = $v;
}

return yield from $result;
return $carry;
};

/** @psalm-var Closure(Iterator<TKey, list<T>>): Generator<int, list<T>> $compose */
$compose = Compose::of()(
FoldLeft::of()($reduceCallback)([]),
Unwrap::of()
);

return $compose;
}
}
18 changes: 7 additions & 11 deletions src/Operation/Wrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,23 @@ final class Wrap extends AbstractOperation
*/
public function __invoke(): Closure
{
$callbackForKeys = static function (): void {
};
$callbackForValues =
$mapCallback =
/**
* @psalm-param T $initial
* @psalm-param TKey $key
* @psalm-param T $value
* @psalm-param TKey $key
*
* @psalm-return array<TKey, T>
*
* @param mixed $initial
* @param mixed $key
* @param mixed $value
* @param mixed $key
*
* @psalm-return array<TKey, T>
*/
static function ($initial, $key, $value): array {
static function ($value, $key): array {
return [$key => $value];
};

/** @psalm-var Closure(Iterator<TKey, T>): Generator<int, array<TKey, T>> $compose */
$compose = Compose::of()(
Associate::of()($callbackForKeys)($callbackForValues),
Map::of()($mapCallback),
Normalize::of()
);

Expand Down

0 comments on commit 13b5d6d

Please sign in to comment.