Git Product home page Git Product logo

optional.dart's Issues

[featurerequest] add orElse to ifPresent

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]);

mapping over empty Optional throws exception

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.

3.0.1 Runtime errors when using `cast`

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.

Optional extension method

Hi @tonio-ramirez

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.

Would like to have a way to get an async value if not present without having to use casts.

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);
  }
}

Github version is not latest released version

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.

Nullable parameter type

Suppose I want an object o of type Optional<String?>, where

  • if !o.isPresent, the user ID is being loaded
  • if o.isPresent and o.value == null, the user has not an ID
  • if o.isPresent and o.value != null, the user has an ID of value o.value

If I create an Optional.of(null), this would incorrectly raise an ArgumentError. If I create an Optional.ofNullable(null), which is equivalent as creating an Optional.empty(), this would incorrectly give an absent-optional when I expected a present-optional containing a null value.

I'm actually wondering if that if-check on Optional.of is really necessary after null-safety. If we can't remove it because of backwards-compatibility, should we create a new constructor for this matter?

factory Optional.present(T value) {
  return _Present<T>(value);
}

Feature request: Contains

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;

OptionalExtension does not support null.toOptional

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

Feature request: nullable orElse

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

Please make empty-constructor const

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.