/** * Returns the position/key of the last item satisfying the * predicate in the array or null if no such element is found. * ```php * findLastIndex(startsWith('b'), ['foo', 'bar', 'baz']); // 2 * findLastIndex(startsWith('b'), ['a' => 'foo', 'b' => 'bar', 'c' => 'baz']); // 'c' * findLastIndex(startsWith('c'), ['foo', 'bar', 'baz']); // null * ``` * * @signature (a -> Boolean) -> [a] -> Maybe(Number) * @signature (v -> Boolean) -> {k: v} -> Maybe(k) * @param callable $predicate * @param array $list * @return mixed */ function findLastIndex() { $findLastIndex = function ($predicate, $list) { foreach (reverse(toPairs($list)) as $pair) { if ($predicate($pair[1])) { return $pair[0]; } } return null; }; return apply(curry($findLastIndex), func_get_args()); }
/** * Converts a variable to its string value. * ```php * toString(53)); // '53' * toString(true)); // 'true' * toString(false)); // 'false' * toString(null)); // 'null' * toString('Hello World')); // '"Hello World"' * toString([])); // '[]' * toString(new \stdClass)); // '{}' * toString(function(){})); // '[Function]' * toString(Error::of('Ooops'))); // '[Error: Ooops]' * toString(fopen('php://temp', 'r'))); // '[Resource]' * toString(['hi', 'hello', 'yo'])); // '["hi", "hello", "yo"]' * toString([ * 'object' => Stream::of(null), * 'numbers' => [1, 2, 3], * 'message' * ]); // '{object: Stream(Null), numbers: [1, 2, 3], 0: "message"]' * ``` * * @signature * -> String * @param mixed $something * @return string */ function toString() { $toString = function ($something) { switch (type($something)) { case 'String': return "\"{$something}\""; break; case 'Boolean': return $something ? 'true' : 'false'; break; case 'Null': return 'null'; break; case 'Number': return (string) $something; break; case 'List': return '[' . join(', ', map(toString(), $something)) . ']'; break; case 'Error': case 'Stream': return $something->__toString(); case 'Object': case 'Array': return '{' . join(', ', map(function ($pair) { return $pair[0] . ': ' . toString($pair[1]); }, toPairs($something))) . '}'; default: return '[' . type($something) . ']'; } }; return apply(curry($toString), func_get_args()); }
/** * Checks if a list of attribute/value of an object/array passes any of the given predicates. * ```php * $persons = [ * ['name' => 'foo', 'age' => 11], * ['name' => 'bar', 'age' => 9], * ['name' => 'baz', 'age' => 16], * ['name' => 'zeta', 'age' => 33], * ['name' => 'beta', 'age' => 25] * ]; * * $isValid = satisfiesAny([ * 'name' => startsWith('b'), * 'age' => gt(__(), 15) * ]); * * filter($isValid, $persons); * // [ * // ['name' => 'bar', 'age' => 9], * // ['name' => 'baz', 'age' => 16], * // ['name' => 'zeta', 'age' => 33], * // ['name' => 'beta', 'age' => 25] * // ] * ``` * * @signature {String: (a -> Boolean)} -> {k : a} -> Boolean * @param array $predicates * @param mixed $object * @return bool */ function satisfiesAny() { $satisfiesAny = function ($predicates, $object) { $predicates = map(function ($pair) { return satisfies($pair[1], $pair[0]); }, toPairs($predicates)); $predicates = apply(_f('any'), $predicates); return $predicates($object); }; return apply(curry($satisfiesAny), func_get_args()); }