Coder Social home page Coder Social logo

Comments (26)

iamarnas avatar iamarnas commented on July 21, 2024 1

What's your opinion ?
@iamarnas

@FatulM I agreed with you. Like I said, it's a taste thing and maybe and bad practice 😁

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024 1

Ok, I will consider this ...
But it may take some time to implement it,
And it will have breaking changes.
Thanks a lot

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024 1

Hi,
I changed implementation according to your recommendation.
Please check out examples to see if it fits your needs.
for example:

weather

@iamarnas

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024 1

Hi,
I changed implementation according to your recommendation.
Please check out examples to see if it fits your needs.
for example:
weather

@FatulM It looks amazing 👍. How to setup this? Or is this by default?

After I'll publish 1.5.0 it will be by default.
I removed @WithWrap annotation.
Now we have *map methods like when not using WithWrap,
And *when methods like when using WithWrap.

If you were using WithWrap you should change all of factory and constructor calls to named args.
Since I don't have any way to distinguish between wrapped and non wrapped state ...

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024 1

This is not a private package!
And I will consider your recommendation ... but it may take some time.
thanks.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

Hi,
I've fixed analyzer version in version 1.3.0.
And now all factories are constant factories for constant immutable sub classes.
For your suggestions about maps and getter, I'll check them at first oppotunity.
Thanks.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

For your first suggestion about maps:
You mean we should use map instead of when ?

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

And about getters, At first I had the same idea.
But there are two points which stops me from using getters ...

  1. using type casts is not a good Programming approach and we should not persuade it. By not using getters we somehow discourage user from using cast methods ! 😁 don't you agree ?
  2. if we make them getters they may be mistaken with sub class fields, or possibly clash names.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

What's your opinion ?
@iamarnas

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

For your first suggestion about maps:
You mean we should use map instead of when ?

No, when and map is a different. map you need add when user generate all @WithWrap()

// When method. 
  R when<R extends Object?>({
    required R Function() loading,
    required R Function(Object error) error,
    required R Function(T data) data,
  }) {
    final result = this;
    if (result is ResultLoading<T>) {
      return loading();
    } else if (result is ResultError<T>) {
      return error(result.error);
    } else if (result is ResultData<T>) {
      return data(result.data);
    } else {
      throw AssertionError();
    }
  }

// Map method.
R map<R extends Object?>({
    required R Function() loading,
    required R Function(ResultError<T> error) error,
    required R Function(ResultData<T> data) data,
  }) {
    final result = this;
    if (result is ResultLoading<T>) {
      return loading();
    } else if (result is ResultError<T>) {
      return error(result);
    } else if (result is ResultData<T>) {
      return data(result);
    } else {
      throw AssertionError();
    }
  }

In short @WithWrap() is not maped data without is maped.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

About map, If I got your problem correctly,
You have a situation which at the same time:

  1. you need @WithWrap,
    (Which the only result of wrapping is changing when method and constructor signatures.)
  2. you need when methods as you are not using @WithWrap

?

Or you need map and when simultaneously ? for example because some tool need map methods ...

A workaround is to generate map and mapOrElse methods when using withWrap as well as when not using withWrap ?

@iamarnas

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

@FatulM Example:

/// With this setup everything will be generated `@WithWrap()`. This should be as default.
@Sealed()
@WithWrap() /// You don't need at all this anotannion because `map` and `mapOrElse` in all case provide all data as map. 
abstract class _Result<T> {
  void loading();
  void data(T value);
  void error(Object error);
}

// All wrapped default methods as expected by setup.
 R when<R extends Object?>({
    required R Function() sunny,
    required R Function(T value) data,
    required R Function(Object error) error,
  }) {
    /* implementing whenOrElse and the rest... */

/// Add both `map`and `whenOrElse` methods only if you detect if user generate everything `@WithWrap()`
 R map<R extends Object?>({
    required R Function() sunny,
    required R Function(Result<T> value) data,
    required R Function(Result<T> error) error,
  }) {
    /*  Add whenOrElse */

This setup should be as default because map and mapOrElse in all case provide all data as map and you don't need annotation@WithWrap() at all or not generate maps methods if you detect that the user generates some function without a wrap, then when and map will be the same method. Example with Freezed you can do most with only with when , maybeWhen, map, maybeMap.

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

@FatulM

For example because some tool need map methods ...

map and mapOrElse in all case provide all data as map.

A workaround is to generate map and mapOrElse methods when using withWrap as well as when not using withWrap ?

Yes, or use may setup as default.

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

@FatulM in short. By adding map or mapOrElse you don't need @WithWrap() annotation at all because map and mapOrElse in all case provide all data as map. And you have everything in one place.

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

Hi,
I changed implementation according to your recommendation.
Please check out examples to see if it fits your needs.
for example:

weather

@FatulM It looks amazing 👍. How to setup this? Or is this by default?

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

please check out changelog:
changelog

I published 1.5.0

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

I will try as soon as I can 😊. As I understand you removed @WithWrap()? Just run builder and everything added in one place?

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

Hi @FatulM

Now I see a big difference and I am happy with this result. I fix the rest with small changes to fits my needs. Example:

Equality

Equality.distinct missing the hashCode, and I don't understand why you can't implement full code when you have all values.

Result by sealed generators:

/// Override `hashCode` if overriding `==`.
/// Note: also implemented in the classes without parameters.
@override
  bool operator ==(Object other) => false;

Should be:

///class [ResultError<T extends Object?, E extends Object?>]
@override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
  
    return other is ResultError<T, E> &&
      other.error == error &&
      other.stackTrace == stackTrace;
  }

  @override
  int get hashCode => error.hashCode ^ stackTrace.hashCode;

Default parameters

I don't know how Dart Build System builders work. But is that not possible to use the same parameters provided by the user. That should be enough only to remove default values from the factory constructor and from all methods. The rest just copy and paste.

@Sealed()
abstract class _Result<T, E> {
 void loading();
 // Default constructor by the user => (E error, [StackTrace stackTrace = StackTrace.empty])
 void error(E error, [StackTrace stackTrace = StackTrace.empty]); 
 void data(T value);
}

const factory Result.error(E error, [StackTrace stackTrace]) = ResultError<T, E>; // <= remove default value from factory constructors

class ResultError<T extends Object?, E extends Object?> extends Result<T, E> {
 // Paste default constructor (E error, [StackTrace stackTrace = StackTrace.empty])
 const ResultError(
   this.error, [
   this.stackTrace = StackTrace.empty,
 ]) : super._internal();

 final E error;
 final StackTrace stackTrace;

 @override
 String toString() => 'Result.error(error: $error, stackTrace: $stackTrace)';
}

R when<R extends Object?>({
   required R Function() loading,
   required R Function(E error, [StackTrace stackTrace]) error, // <= remove default value from the methotds
   required R Function(T value) data,
 }) {
 /*...*/

/// And in the functions need detect optional parameters type `[]` or `{}`
if (result is ResultError<T, E>) {
     return error(result.error, result.stackTrace); // or error(result.error, stackTrace: result.stackTrace);
} 
/*...*/

Otherwise is good work you can close this issue if you want. It's just my suggestion.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

about distinct equality:
overriding hashcode does not make sense since all of instances are not equal to each other.
even an instance is not equal to itself.
what should I return from hashcode ?
If i return a single result for example 0 or runtimeType.hashcode or superclassType.hashcode.
(which is i think the last one is best).
It does not make sense !

If you want that type of equals and hashcode like equatable package you should use data equality.
This is like the functionallity which you have proposed ...

(There are three types of equality
please check their implementation in example folder)

What is your opinion ?

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

And please make another issue about default parameters and copy your recommendation there.
I should investigate the difficulty of implementing that feature.
I thin it is possible but is very hard to implement 😄

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

And also I have changed cast methods to getters on master

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

Thanks for your great suggestions

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

I'm not agreed with you about distinct equality. As you see it is very important for not primitive objects and more important for creating tests.

Just copy and paste in the dart pad to test it.

void main() {
  /// [Counter] with equality operator;
  print(ResultData(Counter(1)) == ResultData(Counter(1))); // true
  print(ResultData(Counter(1)) == ResultData(Counter(2))); // false
  print(ResultData(1) == ResultData(1)); // true
  print(ResultData(1) == ResultData(2)); // false

  // [Counter] without equality operator;
  print(ResultData(Counter(1)) == ResultData(Counter(1))); // false
  print(ResultData(Counter(1)) == ResultData(Counter(2))); // false
  print(ResultData(1) == ResultData(1)); // true
  print(ResultData(1) == ResultData(2)); // false
  
  /// And everything is `false` if [ResultData] does not have an equality operator.
}

class Counter {
  int value;
  Counter(this.value);

  @override
  String toString() => 'Result.data(value: $value)';

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is Counter && other.value == value;
  }

  @override
  int get hashCode => value.hashCode;
}

// Generated by sealed generators
class ResultData<T extends Object?> extends Result<T> {
  const ResultData(this.value) : super._internal();

  final T value;

  @override
  String toString() => 'Result.data(value: $value)';

 // Added by me
  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is ResultData<T> &&
        other.value == value;
  }

  @override
  int get hashCode => value.hashCode;
}

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

I think, pure Dart equality operator would be as default. You really don't need depend you package on Equatable for that, keep your package clean as possible, it better for you and users. You can generate EquatableMixIn but allow to users if they want use it, they can install package self.

from dart_sealed.

FatulM avatar FatulM commented on July 21, 2024

Maybe it is a good approach,
but in 6thsolution we mostly use this package with bloc,
so we need data equality as default

If you want default behavior use Equality.identity

implementing data equality and hashcode by ourself is a goal of dart_sealed,
but it will not be in near future

from dart_sealed.

iamarnas avatar iamarnas commented on July 21, 2024

In 6thsolution we mostly use this package with Bloc.

Oh, I did not know that this package you created for yourself. Then I close this issue 😃
Thanks anyway for great a package.

from dart_sealed.

Related Issues (14)

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.