0 purchases
dfp
dfp #
dfp is a library for typed functional programming in Dart, inspired by Rust.
Result #
Result is a type that represents either success (Ok) or failure (Err).
For example, you can use Result with dio:
import 'package:dfp/dfp.dart';
...
Future<Result<User, String>> fetchUser() async {
final response =
await asyncTryCatch<Response<Map<String, dynamic>>, DioError>(
dio.get(Urls.account),
);
return response
.map((r) => UserDto.fromJson(r.data!))
.map((value) => value.toModel())
.mapErr((error) {
if (error.response?.statusCode == 401) return 'Unauthorized error';
return 'Another error';
});
}
copied to clipboard
In this case, we have converted the successful response to a DTO model, and then we have converted it to a domain model. Also we have converted the error value (if we got it) from DioError to String.
We can use the result value with the provided methods, such as ifOkElse:
// somewhere in BLoC
fetchUser: (_) async {
emit(UserState.loading());
final result = await fetchUser();
result.ifOkElse((user) {
emit(UserState.loaded(user));
}, (error) {
emit(UserState.error(error));
});
},
copied to clipboard
If we don't care about the error, we can use the result.ok value, which also provides many useful methods. For example:
Future<Option<User>> fetchUser() async {
final response =
await asyncTryCatch<Response<Map<String, dynamic>>, DioError>(
_httpClient.get(Urls.account),
);
return response
.map((r) => UserDto.fromJson(r.data!))
.map((value) => value.toModel())
.ok;
}
...
// somewhere in BLoC
fetchUser: (_) async {
emit(UserState.loading());
final result = await fetchUser();
result.ifSomeElse((user) {
emit(UserState.loaded(user));
}, () {
emit(UserState.error());
});
},
copied to clipboard
Instead of result.ifOkElse we can use result.ifOk, result.ifErr or result.when:
result.ifOk((user) {
emit(UserState.loaded(user));
})
...
result.ifErr(error) {
emit(UserState.error(error));
});
...
result.when(
ok: (user) => emit(UserState.loaded(user)),
err: (error) => emit(UserState.error(error)),
);
copied to clipboard
Option #
Option<A> is a container for an optional value of type A. If the value of type A is present, the Option<A> is an instance of Some<A>, containing the present value of type A. If the value is absent, the Option<A> is an instance of None.
An option could be looked at as a collection or foldable structure with either one or zero elements.
Another way to look at Option is: it represents the effect of a possibly failing computation.
The Option class also provides a number of useful methods such as map, ifSome, ifNone, ifSomeElse, and when. These methods work in the same way as the map, ..., when methods of the Result.
You can create an Option object from a nullable value using the Option.fromNullable constructor or the fromNullable function, like this:
final str = Option.fromNullable(stdin.readLineSync());
final number = Option.flatten(
str.map((value) => Option.fromNullable(double.tryParse(value))),
);
final fixed = number
.map(sin)
.map((value) => value * 2)
.map((value) => value.abs().toStringAsFixed(2));
print(fixed.toNullable());
copied to clipboard
toNullable method conversely allows you to turn an Option object into a value of the nullable type.
You can convert an Option to a Result using the okOr method:
final n = Option.fromNullable(double.tryParse('value'));
final result = n.okOr('Not a number'); // Result<double, String>
copied to clipboard
Or you can get the contained Option value using the getOrElse method. It returns the contained Some value or a provided fallback for None:
final n = Option.fromNullable(double.tryParse('value'));
print(sin(n.getOrElse(0)));
copied to clipboard
functions #
dft also provides several functions that can be used to get Option and Result objects:
final value = 5;
final even = option(value.isEven, value);
final nullable = fromNullable(double.tryParse('value'));
final number =
tryCatch<double, FormatException>(() => double.parse('source'));
final result = asyncTryCatch<Response<Map<String, dynamic>>, DioError>(() =>
dio.get(Urls.account));
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.