Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom equality semantics for Immutable.js data structures

I would like Sanctuary to provide Fantasy Land -compatible Map and Set types with value-based equality semantics. Ideally these values would be immutable, though this is not critical since Sanctuary would provide pure functions for merging and otherwise manipulating these values.

I would love to leverage the good work done by the Immutable.js team; I imagine implementing persistent data structures takes considerable effort!

The API provided by Immutable.js is of little importance since Sanctuary would expose functions for interacting with these values. The equality semantics of these types, though, are crucial.

This is unacceptable for my use case:

> Map([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']])
Map { [1,2,3]: "foo", [1,2,3]: "bar" }

[1, 2, 3] is the same value as [1, 2, 3]. It should not be possible to have two map entries with the same key.

The handling of -0 is also problematic:

> Immutable.is(Map([[0, 0]]), Map([[-0, -0]]))
true

I realize it's possible to define the equality semantics of one's own types by defining equals methods, but I wish to redefine the equality semantics of native types such as Array and Number. Is this possible? The relevant file appears to be is.js, but I see no hooks for customization.

It's possible that Sanctuary's Map type could wrap the Immutable.js Map type. This would provide:

  • a way to handle -0;
  • an opportunity to perform value-based equality checks before performing an assoc operation which would normally result in a duplicate key; and
  • a place to define the various fantasy-land/ methods.

Perhaps:

Map k v = { negativeZero :: Maybe v
          , value :: ImmutableMap k v
          , fantasy-land/equals :: Map k v ~> Map k v -> Boolean
          , fantasy-land/map :: Map k v ~> (k -> a) -> Map a v
          , fantasy-land/bimap :: Map k v ~> (k -> a, v -> b) -> Map a b
          , ...
          }

I'd like to be sure there's no other way to attain the desired equality semantics before creating wrappers such as the above. facebook/immutable-js#519 isn't promising.

like image 936
davidchambers Avatar asked Sep 18 '16 11:09

davidchambers


People also ask

Why apps are built on immutable data structure?

Besides reduced memory usage, immutability allows you to optimize your application by making use of reference- and value equality. This makes it really easy to see if anything has changed.

Why we need Immutable js?

Immutable. js is a library that supports an immutable data structure. It means that once created data cannot be changed. It makes maintaining immutable data structures easier and more efficient.

What is TOJS?

tojs lets you convert files between plain text, javascript strings, and document. write() statements. It's original purpose, was to read in an . html file, and output it as a series of document.

Is map immutable Javascript?

js provides many Persistent Immutable data structures including: List , Stack , Map , OrderedMap , Set , OrderedSet and Record .


1 Answers

Although this was asked long ago I don't see a reference to this simple solution:

const {Map, fromJS} = Immutable

// instead of this:
console.log(
  Map([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']]).toString(),
)

// do this:
console.log(
  Map(fromJS([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']])).toString()
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/4.0.0-rc.12/immutable.min.js"></script>

By deeply converting the objects using fromJS you get the value equality

like image 196
thedude Avatar answered Nov 15 '22 20:11

thedude