Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> What do you mean by persistent here?

I mean the class of data structures called persistent: https://en.wikipedia.org/wiki/Persistent_data_structure

> I assume some kind of shared memory instead of copying?

Sure.

> I am surprised where this sentiment comes from. Because of the initial comment?

Because "tuple" for an immutable sequence is rather specific to Python.

And data structures related to clojure (or functional languages in general) would have some sort of logarithmic component because they'd be tree-based. Pretty much the only O(1) operation in functional data structures is prepending to a linked list.



Thanks for clarifying, I did not find anything decisive searching persistent in combination with Clojure, weird.

> Because "tuple" for an immutable sequence is rather specific to Python.

As someone with a background in Swift, Rust and C#, all of which have the concept of a tuple, I did not make that connection, but thanks again.


> As someone with a background in Swift, Rust and C#, all of which have the concept of a tuple

They all have tuples, but AFAIK in none of them is a tuple a sequence (well not sure about C# it might be there, but I'd be surprised). Usually a tuple is a form of lightweight, anonymous, structure, so it's addressed by field (even if the fields are positions), you usually can't iterate through tuples, or "index" them using runtime variables (except through reflection).

That it is so in Python is somewhat peculiar, but makes sense within the context of the language (unpacking works on iterables, and thus sequences).


The .NET Tuple types Tuple<T1,…> and ValueTuple<T1,…> are not sequences — though the ITuple interface does enable item access by index without reflection — and ValueTuple<T1,…> instances are mutable, but .NET actually has two different immutable sequence types, ImmutableArray<T> and ImmutableList<T>, which are functionally similar but have different performance characteristics[1].

Along with the rest of the .NET immutable collection types[2], both are persistent data structures in the sense noted above.

In contrast, .NET tuple types are, as you say, lightweight, anonymous structures addressed by field. The ValueTuple<T1,…> types, in particular, are used in the underlying implementation of the C# tuple language feature[3].

AFAIK, Python has no built-in anonymous mutable structure types, though since type names in Python are basically only used for display purposes, you can easily create them at runtime, e.g.,

    def anon(**kwargs):
        class _:
            __slots__ = tuple(kwargs.keys())
    
            def __repr__(self):
                return 'anon(' \
                    + ', '.join((f'{i}={getattr(self, i)!r}' \
                                 for i in self.__slots__)) \
                    + ')'
    
            def __eq__(self, other):
                if not hasattr(other, '__slots__') \
                   or sorted(self.__slots__) \
                   != sorted(other.__slots__):
                    return False
                for i in self.__slots__:
                    if getattr(self, i) != getattr(other, i):
                        return False
                return True
            
        o = _()
        for k,v in kwargs.items():
            setattr(o, k, v)
        return o
    
Note that this differs in two notable ways from C# tuples:

1. Each object created has a unique type, so

    type(anon(x=1, y=2)) != type(anon(x=1, y=2))
More importantly, this means a distinct type object is created and stored for every call to anon, which could have significant performance implications at scale.

This could be easily fixed with a cache of already-created anonymous types (trading off slightly increased object-creation time, of course).

2. Equality in the above implementation is based on the equality of identically-named values rather than identically positioned values; in C#, we have

    (x: 1, y: 2) != (y: 2, x: 1)
and

    (x: 1, y: 2) == (y: 1, x: 2),
while in my implementation,

    anon(x=1, y=2) == anon(y=2, x=1)
and

    anon(x=1, y=2) != anon(y=1, x=2).
This was by choice, as it seems more intuitive; C# behavior is no more difficult to implement.

For read-only anonymous structure types, the Python standard library has namedtuple[4] (which, incidentally, bases value equality on position, not attribute name, so C#'s behavior is arguably more "Pythonic" than my own).

[1] https://learn.microsoft.com/en-us/dotnet/api/system.collecti...

[2] https://learn.microsoft.com/en-us/dotnet/api/system.collecti...

[3] https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...

[4] https://docs.python.org/3/library/collections.html#collectio...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: