-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change the approach to Option and Result iteration #185
Conversation
Previously iterating Some and Ok objects depended on whether the underlying type T was iterable or not. If it was the results of the iteration were obtained by iterating the underlying value. There could be an arbitrary number of results. For example this was the case *before* (using Some to demonstrate the idea, the same applies to Ok): // Some<number>, no results because 1 is not iterable for (const e of Some(1)) { ... } // Some<number[]>, two results produced for (const e of Some([1, 2])) { ... } // Some<number[]>, no results produced because the underlying value // contains no items for (const e of Some([]) as Option<number[]>) { ... } This mode of operation never quite worked for me because: 1. It depended on the underlying value being iterable and didn't provide any value in case of numbers, strings and other non-iterable values. 2. It made it impossible to use iteration of Option and Result values to conditionally run some code only when dealing with Some and Ok instances. This patch tackles both of these issues at once (they're connected). The change brings the iteration behavior in line with how Rust's Option and Result do things[1] (zero-or-one iteration resuls, never multiple results). If one needs the old behavior it can be achieved with a little bit of additional code, it's not the case in the opposite direction. For example: const ids: Option<number[]> = ... // Previously: for (const id of ids) { ... } // Now (one of potential solutions): for (const id of ids.unwrapOr([])) { ... } [1] https://doc.rust-lang.org/std/option/enum.Option.html#method.iter
const values = Array.from(Ok('hello')); | ||
expect(Array.from(Ok('hello'))).toEqual(['hello']); | ||
expect(Array.from(Ok([1, 2, 3]))).toEqual([[1, 2, 3]]); | ||
expect(Array.from(Ok(1))).toEqual([1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we have some tests for Err
here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already present in err.test.ts
as:
test('iterable', () => {
for (const item of Err([123])) {
expect_never(item, true);
throw new Error('Unreachable, Err@@iterator should emit no value and return');
}
});
One of these days I'll merge these test files, the split always confuses me.
const o: Option<number[]> = Some([1, 2, 3]) | ||
const rs = Array.from(o) | ||
// Previously: rs was [1, 2, 3] | ||
// Now: rs equals [[1, 2, 3]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is super clear 👍
Previously iterating Some and Ok objects depended on whether the underlying type T was iterable or not.
If it was the results of the iteration were obtained by iterating the underlying value. There could be an arbitrary number of results.
For example this was the case before (using Some to demonstrate the idea, the same applies to Ok):
This mode of operation never quite worked for me because:
This patch tackles both of these issues at once (they're connected).
The change brings the iteration behavior in line with how Rust's Option and Result do things[1] (zero-or-one iteration resuls, never multiple results).
If one needs the old behavior it can be achieved with a little bit of additional code, it's not the case in the opposite direction. For example:
[1] https://doc.rust-lang.org/std/option/enum.Option.html#method.iter