GithubHelp home page GithubHelp logo

Comments (7)

zellidev0 avatar zellidev0 commented on June 2, 2024 1

@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.
Basically I'm transforming a compile time error to a runtime error. Do you agree?

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.

from fpdart.

SandroMaglione avatar SandroMaglione commented on June 2, 2024

Hi @zellidev0

The $ function inside the Do notation cannot be used nested inside a function callback (.map in your example) or in a for condition.

Instead, I would suggest to refactor your code as follows (I added a test for Option):

test('should traverse over a list', () async {
const testOption = const Option<List<String?>>.of(
['/', '/test', null],
);
Option<List<Uri>> doNotation = Option.Do(
($) {
List<String?> optionList = $(testOption);
return $(optionList.traverseOption(
(stringValue) => optionOf(stringValue).flatMap(
(uri) => optionOf(
Uri.tryParse(uri),
),
),
));
},
);
expect(doNotation, equals(const Option<Uri>.none()));
});

$ allows to extract the value of an Option inside the .Do constructor function.

from fpdart.

SandroMaglione avatar SandroMaglione commented on June 2, 2024

@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:

  • Throwing inside Do constructor
  • Using await without executing the $ function
  • Not using $ nested

I agree that we should add these points to the documentation. Mind opening a PR for this?

from fpdart.

zellidev0 avatar zellidev0 commented on June 2, 2024

@SandroMaglione that's a good idea.
Please assign the issue to me.

I created a Pull request here.

from fpdart.

danielRi avatar danielRi commented on June 2, 2024

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):

Throwing inside Do constructor
Using await without executing the $ function
Not using $ nested

Exptected behavior:

I would expect here the code just "jumps" to the getOrElse part, because an Option returns None.

from fpdart.

zellidev0 avatar zellidev0 commented on June 2, 2024

@danielRi I think the issue is with using a async callback in the Option.Do(...) constructor.
When having to use async you should use a Task and the TaskEither etc. types.

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.
You can omit the match in this case and do the LocaleKeys... in your view logic when calling match.

from fpdart.

SandroMaglione avatar SandroMaglione commented on June 2, 2024

@danielRi as @zellidev0 mentioned the issue is using async inside Do without _:

final either = await _actionRepo.parseArguments(formData); // Use `_` here

Another suggestion is to remember not to use print inside pure code. print causes side effects.

from fpdart.

Related Issues (20)

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.