simc / dartx

Superpowers for Dart. Collection of useful static extension methods.
https://pub.dev/packages/dartx
Apache License 2.0
1.08k stars 88 forks source link

feat: Add deep copy for List and Map #159

Closed myConsciousness closed 2 years ago

myConsciousness commented 2 years ago

Hi amazing developers,

I added utilities for deep copying of List and Map :)

myConsciousness commented 2 years ago

cc @passsy @leisim

passsy commented 2 years ago

That's not a deep copy. It is a normal copy like the official toList()

Here's the proof

    test('deep copy', () {
      final list = [1, 2, [3, 4]];
      final clone = list.clone();

      expect(clone, [1, 2, [3, 4]);
      expect(clone == list, false);

      // add item to original
      (list[2] as List).add(5);
      expect(list, [1, 2, [3, 4, 5]);

      // both fail because sub collections are copied by reference, not cloned
      expect(clone, [1, 2, [3, 4]);
      expect(identical(list[2], clone[2]]), isFalse);
    });
myConsciousness commented 2 years ago

Thanks for your review and feedback @passsy !

I didn't know this fact, thanks for your testing! Then it would have to be classically recursively cloned, and also maybe it should be implemented in Object and with Clonable interface.

myConsciousness commented 2 years ago

Okay I found a trick like below.

extension ListCloneExtension<E> on List<E> {
  /// Returns a deep copied list with the same elements as this [List].
  dynamic clone() => jsonDecode(jsonEncode(this));
}

This method uses serialization and deserialization, but the return type is dynamic. Also, this method does not seem to be versatile enough to be applied to Map. However, it can be used for List collections.

Can you give me your opinion on this method @passsy ?

passsy commented 2 years ago

It only works for classes that are serializable. Unfortunately, there is no interface for it so that we can detect it reliably.

Your clone method wouldn't work for most classes that's why I don't see it as part of dartx. It's not general enough.

Let's wait for data classes or static metaprogramming or Algebraic Data Types to land in dart. These features might enable this feature.