tonio-ramirez / optional.dart Goto Github PK
View Code? Open in Web Editor NEWAn implementation of the Optional type for Dart
License: BSD 2-Clause "Simplified" License
An implementation of the Optional type for Dart
License: BSD 2-Clause "Simplified" License
When I have time I can give a code example, but the basic setup was an Optional of type T (absent), casted to R (.cast<R>()
) and then orElse(instanceOfR)
was throwing a runtime error which described the problem as expected T but got R.
On 3.0.0, I do not get this error.
Hi @tonio-ramirez,
When using the library in a null safe context it becomes difficult to get a null out of the Optional without being verbose and using if statements or using map<T?>(identity)
.
final Optional<String> data = Optional.of("data");
final String? value = data.orElse(null);
Fails analysis with
Error: The value 'null' can't be assigned to the parameter type 'String' because 'String' is not nullable.
Adding these to the library would make life easier
T? orElseNullable(T? other)
T? get orElseNull
Thanks again for the awesome library!
James
import 'package:optional/optional.dart';
void main() {
Optional<int> b = Optional.of(33);
print(b); // Optional[value: 33]
print(b.map((i) => i/2)); // Optional[value: 16.5]
Optional<int> c = Optional.empty();
print(c); // Optional[empty]
print(c.map((i) => i/2)); // Unhandled exception: type '_Absent<dynamic>' is not a subtype of type 'Optional<double>'
Optional<int> d = Optional.ofNullable(null);
print(d); // Optional[empty]
print(d.map((i) => i/2)); // Unhandled exception: type '_Absent<dynamic>' is not a subtype of type 'Optional<double>'
}
In the above snippet, map
operations over an empty Optional result in an exception.
The expectation was for an empty Optional to silently remain unchanged when mapped over. I'm used to working with scala's Options, which work this way. A quick look suggests that java's Optional also works the way I expect.
Could you please add a "orElse" to ifPresent?
void ifPresent(void consume(T val),{ void orElse() }) {
if(isPresent) {
consume(_value);
} else if(orElse != null) {
orElse();
}
}
void ifPresent(void consume(T val)) => Function.apply(consume, [_value]);
First of all: Thanks for your lib!
Features request:
factory RestStatus(final int code, final String description, final String reason,{ final Optional<List<String>> stacktrace = const Optional.empty(), final Optional<Uri> uri = const Optional.empty()}) {
return new RestStatus._internal(new RestStatusData(code,description,reason,stacktrace,uri));
}
As you can see - it would be cool to give Darts optional values an Optional data type.
Thanks
I want to load a chat if one is present or else create one asynchronously.
Lets imagine i have a chat app.
What I would like to write is something like this:
Future<ChatView> loadOrCreateChat(String id) async {
final maybeChat = await repository.loadChat(id);
final chat = await maybeChat.orElseGetAsync(() => _createChat(id));
return chatViewFactory.createView(chat);
}
What I have to write is:
Future<ChatView> loadOrCreateChat(String id) async {
final maybeChat = await repository.loadChat(id);
final casted = maybeChat.cast<FutureOr<Chat>>();
final chat = await casted.orElseGet(() => _createChat(id));
return chatViewFactory.createView(chat);
}
Basically I dont want to cast manually.
Here is a minimal example:
import 'dart:async';
import 'package:optional/optional.dart';
import 'package:test/test.dart';
void main() {
ChatViewLoader bloc;
ChatRepository repository;
setUp(() {
repository = ChatRepository();
bloc = ChatViewLoader(repository, ChatViewFactory());
});
test('creates chat if chat from repo is empty', () async {
repository.returnEmpty = true;
final view = await bloc.loadOrCreateChat('id');
expect(view.fromRepo, false);
});
test('does not create chat if chat from repo is non-empty', () async {
repository.returnEmpty = false;
final view = await bloc.loadOrCreateChat('id');
expect(view.fromRepo, true);
});
}
class ChatViewLoader {
final ChatRepository repository;
final ChatViewFactory chatViewFactory;
ChatViewLoader(this.repository, this.chatViewFactory);
Future<Chat> _createChat(String id) async {
return Chat(false);
}
Future<ChatView> loadOrCreateChat(String id) async {
final maybeChat = await repository.loadChat(id);
final casted = maybeChat.cast<FutureOr<Chat>>();
final chat = await casted.orElseGet(() => _createChat(id));
return chatViewFactory.createView(chat);
}
}
class ChatRepository {
bool returnEmpty = true;
Future<Optional<Chat>> loadChat(String id) async {
return returnEmpty ? Optional.empty() : Optional.of(Chat(true));
}
}
class Chat {
final bool fromRepo;
Chat(this.fromRepo);
}
class ChatView {
final bool fromRepo;
ChatView(this.fromRepo);
}
class ChatViewFactory {
Future<ChatView> createView(Chat chat) async {
return ChatView(chat.fromRepo);
}
}
Any chances the ^6.0.0-nullsafety.2 will become the 6.0.0 release sooner rather than later?
To save HEAPS of code unwrapping or mapping it would be great to have a contains. Currently I have to:
T t = ...;
Optional<T> o = Optional.of(t);
bool contains1 = o.map((v)=>v == t).orElse(false);
bool contains2 = o.isPresent ? o.value == t : false;
Suggested signature and implementation
Signature:
bool contains(T val);
Absent:
bool contains(T val) => false;
Present:
bool contains(T val) => _value == val;
Hi @tonio-ramirez,
Can you please revert the change made to OptionalExtension
as it no longer handles null values with toOptional.
Optional<T> get toOptional => Optional.of(this);
Should be
Optional<T> get toOptional => Optional.ofNullable(this);
Missing test case for test/src/extension.dart
test('null.toOptional == Optional.empty()', () {
expect(null.toOptional, equals(Optional.empty()));
});
Many thanks!
James
I have a proposal to include an extension method for creating Optionals which avoids wrapping every instance you create in the factory constructor Optional.of()
.
The syntax extension makes it possible to write this following:
Optional<MyObject> oMo = Optional.of(mo);
like this instead:
Optional<MyObject> oMo = mo.toOptional;
It is also has the benefit that it becomes about 10 times quicker to construct the Optional as you get code completion from the IDE!
import 'package:optional/optional.dart';
extension OptionalExtension<T> on T {
Optional<T> get toOptional => Optional.ofNullable(this);
}
The only downside when making this change is it increases the SDK dependency for Dart from 2.0.0 to 2.6.0 to get the new language feature.
My personal view on the SDK dependency is that the current state of the library is extremely "stable" such that anyone on who requires a <2.6.0 SDK dependency is most likely going to be require any bug fix releases.
You could probably get away with a major version bump to v4 to accompany the change if you wanted to keep the door open for a legacy v3 branch for any bug fixes which may happen where you wanted to maintain 2.0.0 compatibility.
Github code works fine when mapping empty optionals because of added 'cast' method:
@override
Optional<R> map<R>(R mapper(T val)) => empty.cast();
but this cast
is missing in https://pub.dartlang.org/ official release
@override
Optional<R> map<R>(R mapper(T val)) => empty;
-- edit --
Looks like Github version is not working either - I've submitted PR.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.