Skip to content

Instantly share code, notes, and snippets.

@Avaq
Last active August 18, 2021 10:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Avaq/ee2c6c819db4c37258e9a226e6380a38 to your computer and use it in GitHub Desktop.
Save Avaq/ee2c6c819db4c37258e9a226e6380a38 to your computer and use it in GitHub Desktop.
Breaking Changes Upgrade Guide for Fluture version 12

Fluture v12 Upgrade Guide

Modular version made compatible with Node 12

The modular version of Fluture no longer works with Node version 9, 10, and 11 using --experimental-modules. In order to load the modular version into those runtimes, one has to use the esm loader.

Furthermore, the modular code must now be "deep" imported from fluture/index.js. That is, import 'fluture/index.js' for EcmaScript modules, or require ('fluture') for CommonJS modules.

Future constructor no longer overloaded

It is no longer possible to construct a Future using the Future constructor without explicitly returning a cancellation function. If you have no way to cancel the underlying computation, you should return noop as a cancellation function.

Promise function reworked

See fluture-js/Fluture#331. In order to call promise on a Future, the rejection branch must now be compatible with type Error, and thrown exceptions are now merged with the rejection branch, instead of being rethrown.

This means you can now use coalesce and promise together to create Promises that capture exceptions, rejections, and resolutions, each in their own branch.

Anywhere you're using promise on a Future which doesn't have Error as its rejection type, you have to mapRej it to an Error type first, or coalesce it out of the rejection branch to avoid mixing types in your Promise rejection branch.

Anywhere you're using promise on a Future which does have Error as its rejection type, you now have a choice:

  1. Leave it untouched, and risk mixing expected failures with exceptions in your Promise rejections; or
  2. use coalesce to move your rejection to the resolution branch prior to calling promise.

Functions use simple currying

Anywhere you're calling Fluture's static functions, change , to )(. Or better yet, ) ( (see sanctuary-js/sanctuary#438).

If multiple arguments are provided to a function at once, a TypeError will be thrown.

Fluent method API removed

All methods except pipe have been removed. Pipelines can be expressed in several ways.

  1. Using the esnext pipe operator:

    - resolve (41) .chain (after (10)) .map (x => x + 1)
    + resolve (41) |> chain (after (10)) |> map (x => x + 1)
  2. Using the pipe method from Fluture:

    - resolve (41) .chain (after (10)) .map (x => x + 1)
    + resolve (41) .pipe (chain (after (10))) .pipe (map (x => x + 1))
  3. Using pipe from Ramda or Sanctuary, flow from lodash, or anything similar:

    - resolve (41) .chain (after (10)) .map (x => x + 1)
    + S.pipe ([resolve, chain (after (10)), map (x => x + 1)]) (41)
  4. You can use fluenture to easily upgrade an existing codebase:

    - resolve (41) .chain (after (10)) .map (x => x + 1)
    + fluent (resolve (41)) .chain (after (10)) .map (x => x + 1)

Aliases removed

  • do: Dropped in favour of go.
  • finally: Dropped in favour of lastly.
  • or: Dropped in favour of alt.
  • try: Dropped in favour of attempt.
  • of: Dropped in favour of resolve.
  • new Future: Dropped in favour of Future. This applies to TypeScript only.

Functions renamed

  • tryP was renamed to attemptP to be consistent with the naming of encase and attempt.
  • fold was renamed to coalesce to be more consistent with naming conventions in the functional community.

Static constructor properties removed

The Future and Par exports no longer contain static properties. This means Static Land is no longer supported by these type representatives. The following functions were removed:

  • Future.resolve and Future.reject: You can use the static resolve and reject exports instead.
  • Future.alt and Par.alt: You can use the static alt export.
  • Future.ap and Par.ap: You can use the static ap export.
  • Future.map and Par.map: You can use the static map export.
  • Future.chain: You can use the static chain export.
  • Future.bimap: You can use the static bimap export.
  • Future.of and Par.of: You can use a Fantasy Land dispatcher, such as S.of instead. For Future.of, you could also use the resolve function.
  • Par.zero: You can use a Fantasy Land dispatcher, such as S.zero instead.

Note that the CommonJS version of Fluture still assigns functions of the names mentioned above to the Future constructor, simply because that's how CommonJS works with default exports. But these are not the Static Land compatible functions anymore.

Arguments to some functions were flipped

Anywhere you're calling one of the following static binary functions, the argument order must be inverted.

  • alt
  • and
  • ap
  • race (note that in most cases, the argument order doesn't actually matter)

Fantasy Land 0 support dropped

If you're using an old enough Fantasy Land dispatching library, such as Ramda prior to version 0.24.0, it will no longer work with Fluture. Consider switching to a dispatcher library that supports Fantasy Land 1 and up, or using Fluture's built-in dispatchers.

encaseN, encaseN2, and encaseN3 removed

These functions have been removed, because they were a source of increased API surface and confusion, and their effects can easily be achieved using arrow functions and node, or using functional composition and currying. This new approach can be scaled to any number of arguments.

- const f = encaseN (g)
+ const f = compose (node) (curry (g))
or
+ const f = x => node (c => g (x, c))
- const f = encaseN2 (g)
+ const f = compose (compose (node)) (curry (g))
or
+ const f = x => y => node (c => g (x, y, c))
- const f = encaseN3 (g)
+ const f = compose (compose (compose (node))) (curry (g))
or
+ const f = x => y => z => node (c => g (x, y, z, c))

encase2 and encase3 removed

These functions have been removed, because they were a source of increased API surface and confusion, and their effects can easily be achieved using arrow functions and encase, or using functional composition and currying. This new approach can be scaled to any number of arguments.

- const f = encase2 (g)
+ const f = compose (encase) (curry (g))
or
+ const f = x => encase (y => g (x, y))
- const f = encase3 (g)
+ const f = compose (compose (encase)) (curry (g))
or
+ const f = x => y => encase (z => g (x, y, z))

encaseP2 and encaseP3 removed

These functions have been removed, because they were a source of increased API surface and confusion, and their effects can easily be achieved using arrow functions and encaseP, or using functional composition and currying. This new approach can be scaled to any number of arguments.

- const f = encaseP2 (g)
+ const f = compose (encaseP) (curry (g))
or
+ const f = x => encaseP (y => g (x, y))
- const f = encaseP3 (g)
+ const f = compose (compose (encaseP)) (curry (g))
or
+ const f = x => y => encaseP (z => g (x, y, z))

Fluture internals changed

When upgrading Fluture to this version, make sure all dependencies use the upgraded version of Fluture as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment