-
Notifications
You must be signed in to change notification settings - Fork 43
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
Do Notation throws instance of '_OptionThrow' #139
Comments
Hi @zellidev0 The Instead, I would suggest to refactor your code as follows (I added a test for fpdart/packages/fpdart/test/src/option_test.dart Lines 710 to 729 in d2d21ad
|
@SandroMaglione thanks for the response. This is unfortunate because I have to be careful not to accidentally use a callback in a do constructor and the compiler isn't telling me I'm creating a exception. When not using the do constructor the compiler would tell me if I'm extracting the content of a option etc. Do you have any plans in creating a version of the do constructor that creates a compile time error in these cases? And if not should we update the docs of the do constructor part in the package documentation? Because If i hadn't implemented it that way I would not have found out that this is an issue. |
@zellidev0 the Do notation helps to make the code more readable but comes with some trade offs (reference to the full discussion). You are technically allowed to execute code that can error, but once you know what should be avoided the Do notation becomes really convenient. Some patterns to avoid are:
I agree that we should add these points to the documentation. Mind opening a PR for this? |
@SandroMaglione that's a good idea. I created a Pull request here. |
Hey! I got the exact same issue, but apart from changing an Either to an option and using async/await I wouldnt know why this isnt a normal example where the code just jumps to the getOrElse() part, instead throws _OptionThrow. Future<ResultState> _handleInit(
Init event, Emitter<ResultState> emit) {
return Option.Do((_) async {
final vin = _(_selectedVehicleRepo.vin);
final formData = _(_formDataRepo.load());
final either = await _actionRepo.parseArguments(formData);
print(either); // prints Left(error), as expected
final optionActionResponse = Option.fromEither(either);
print(optionActionResponse); // prints None, as expected
final actionResponse = _(optionActionResponse); // throws Error: Instance of '_OptionThrow'
return ResultState.loaded(
result: '123',
);
}).getOrElse(() async {
return ResultState.error(LocaleKeys.exception_thrown.tr());
});
} I think I dont violate any of these rules here, or am I mistaken (not sure about the 2nd one):
Exptected behavior: I would expect here the code just "jumps" to the getOrElse part, because an Option returns None. |
@danielRi I think the issue is with using a async callback in the Task<ResultState> _handleInit(
Init event,
Emitter<ResultState> emit,
) => Option.Do((_) async {
final vin = _(_selectedVehicleRepo.vin);
final formData = _(_formDataRepo.load());
})
.toEither(() => 'Error extracting vehicleRepoVin or formData')
.toTaskEither()
.map((formData) => _actionRepo.parseArguments(formData))
.match(
(_) => ResultState.error(LocaleKeys.exception_thrown.tr()),
(result) => ResultState.loaded(
result: result,
),
); Also: You don't need the ResultState, you can simply return a TaskEither<Object,YourDataType> from the function. |
@danielRi as @zellidev0 mentioned the issue is using final either = await _actionRepo.parseArguments(formData); // Use `_` here Another suggestion is to remember not to use |
In version
1.1.0
of fpdart:The following code snippet is a simplified version of a piece of code that had a runtime error.
I assume, because I'm mapping over the List of testOption the
Option.Do
constructor does not catch the throwing of_OptionThrow
.I assumed that the exception would be caught by the do Constructor, but this was not the case.
Here is the problematic snippet:
Here is the thrown exception:
Here is a rewrite without a callback that correctly catches the thrown exception and returns none
This is pretty dangerous, because I don't have the type safety at compile time but have a runtime error I totally oversaw in the code review.
How should I proceed with this?
Could the Do constructors implementation be fixed so that callbacks can be used inside, or is this a language limitation and I therefore can't use the Do constructor when Using callbacks (which would be hard, because mapping lists etc is not possible anymore)?
Thanks.
The text was updated successfully, but these errors were encountered: