Open bartfeenstra opened 7 years ago
Maybe add assertSome and assertAll to check that all items match or that there exists a matching item? Although assertSome would probably not be as useful.
Thanks for the review! ::assertAll()
would be like the current ::assert()
behavior in this PR (bail as soon as one item is found that does not meet the conditions). Do we know use cases for::assertSome()
/::assertAny()
? I'm trying to come up with one where we'd want to bail out of processing an iterable if not at least one item meets a condition (meaning n-1 items can still NOT meet the condition). This is keeping in mind that assertions are more a development tool than a simple condition check: use them only when you really want things to fail.
Also note that my original use case for this PR was to ensure an iterable is a proper list or map (all keys and values share the same type), so I'll have to take some time to try and come up with ::assertSome()
use cases as well :)
While biking from the office just now I realized the iterator behavior of this method is identical to that of ::each()
: perform an action with possible side effects for each item, without producing a result (that's why they both provide a fluent interface for daisy chaining). From this perspective we've got the same dilemma as with https://github.com/bartfeenstra/fu-php/issues/61: do we want to provide such shortcut methods on our primary interface, if they can easily be composed by two other methods as well? Assertions with ::each()
would look like this:
$iterator->each(function ($value) {
assert($value instanceof Foo);
})->map(...);
versus
$iterator->assert(P\instance_of([Foo::class])->map(...);
Using ::each()
we have maximum flexibility. ::assert()
is shorter and easy to read, but limited to using predicates (which contribute to the fact it's shorter) and it can only throw exceptions of a single type, meaning it's more useful for debugging, and less for runtime checks where exceptions are used to catch recoverable problems, as API-specific exceptions cannot be thrown.
https://github.com/bartfeenstra/fu-php/pull/68#issuecomment-330353701 proposes ::assert()
takes an optional second parameter which is an operation (like ::each()
takes) and throws the exception. Although then the syntax becomes arguably more verbose than when using ::each()
directly.
Add
Iterator::assert()
that raises an exception if the given predicate does not apply to an item.