Code Monkey home page Code Monkey logo

Comments (4)

marcglasberg avatar marcglasberg commented on June 28, 2024 1

I think that's too complex, making people think about equality, objects being replaced or not, and forcing users to think about if it returns a new instance or the same instance. The update method is a convenience method that's already complex to use, and it's not meant to be useful in all use cases. If users need more specific method they can implement their own, and even add them as extension methods.

from fast_immutable_collections.

marcglasberg avatar marcglasberg commented on June 28, 2024

Currently it returns a new IMap instance:

} else {
      map[key] = updatedValue;
    }

Note I can't compare the updated value with the original value by equality, because equality may return true when objects are different (even if it shouldn't), and also objects in a map may be mutable (even if they shouldn't) so I can't really assume you don't want to replace it if it's equal (you may want to replace it to modify it later).

However, I can optimize it to check if the update callback returns the exact same instance (compare by identity), and in this case yes, return the same IMap instance.

I can specify this in the docs, but that's an implementation detail. I don't think your app should depend on this fact in any way.

from fast_immutable_collections.

marcglasberg avatar marcglasberg commented on June 28, 2024

Done. It now returns the same IMap instance. This is the new code and documentation:

/// Updates the value for the provided [key].
  ///
  /// 1. If the key is present:
  ///
  /// Invokes [update] with the current value and stores the new value in the
  /// map. However, if [ifRemove] is provided, the updated value will first
  /// be tested with it and, if [ifRemove] returns true, the value will be
  /// removed from the map, instead of updated. Note: If [update] returns
  /// the same INSTANCE as the current value, the original map instance will
  /// be returned, unchanged.
  ///
  /// 2. If the key is NOT present:
  ///
  /// If [ifAbsent] is provided, calls [ifAbsent] and adds the key with the
  /// returned value to the map. If the key is not present and [ifAbsent] is
  /// not provided, return the original map instance, without modification.
  /// Note: If you want [ifAbsent] to throw an error, pass it like
  /// this: `ifAbsent: () => throw ArgumentError();`.
  ///
  /// If you want to get the original value before the update/removal,
  /// you can provide the mutable [previousValue] parameter, which is
  /// of type [Output].
  ///
  @useResult
  IMap<K, V> update(
    K key,
    V Function(V value) update, {
    bool Function(K key, V value)? ifRemove,
    V Function()? ifAbsent,
    Output<V>? previousValue,
  }) {
    // 1. If the key is present:
    if (containsKey(key)) {
      final Map<K, V> map = unlock;

      final originalValue = map[key] as V;
      final updatedValue = update(originalValue);

      previousValue?.save(originalValue);

      // 1.1 Value removed
      if (ifRemove != null && ifRemove(key, updatedValue)) {
        map.remove(key);
        return IMap._unsafeFromMap(map, config: config);
      }
      // 1.2 Value updated
      else {
        map[key] = updatedValue;

        return identical(updatedValue, originalValue)
            ? this
            : IMap._unsafeFromMap(map, config: config);
      }
    }
    //
    // 2. If the key is NOT present:
    else {
      previousValue?.save(null);

      // 2.1 IfAbsent is provided
      if (ifAbsent != null) {
        final updatedValue = ifAbsent();
        final Map<K, V> map = ListMap.fromEntries(
          entries.followedBy([MapEntry(key, updatedValue)]),
          sort: config.sort,
        );
        return IMap._unsafeFromMap(map, config: config);
      }
      //
      // 2.2 IfAbsent NOT provided
      else {
        return this;
      }
    }
  }

from fast_immutable_collections.

busslina avatar busslina commented on June 28, 2024

Thank you.

Note I can't compare the updated value with the original value by equality, because equality may return true when objects are different (even if it shouldn't), and also objects in a map may be mutable (even if they shouldn't) so I can't really assume you don't want to replace it if it's equal (you may want to replace it to modify it later).

Why don't just letting the programmer to properly handle the equality for their objects and just aborting (by returning the same IMap instance) when both objects are "equals"?

from fast_immutable_collections.

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.