I think when discussing tuples one should consider the [...]any type as an 
alternative to []any. Arrays supports comparison, aren't boxed and are 
generally more tuple-like. They can be used as map keys.
Of course, they're still not really type-safe. Structs solve that and also 
support access by name instead of by index, so they're better in general.
I have to say that whenever I've used tuples (in C++ and Python) or arrays 
in Go (usually [2]string), I've ended up regretting it and switching to a 
struct/class later.

> I tried but a[i].(T) will not take T as reflect.TypeOf.

I think this is typically written as switch reflect.TypeOf(a[i]).Kind(), 
which gives you the underlying type (e.g. int instead of MyInt). You can 
then use reflect.ValueOf(a[i]).Int() and the sibling functions to access 
the value.
Doing switch a[i].(type) is also possible but that doesn't support custom 
types.

> I would agree, except there is no == operator defined on slices, and I'm 
not really sure why that is. The semantics I would expect are 
straightforward: i.e. length is the same, and the first 'len' slice 
elements compare as equal, recursively if necessary.

Implementing it this way would require dereferencing the internal pointer, 
which could cause infinite loops if the array contains a reference to 
itself. For example, this code panics because it runs out of stack (it's 
hard to tell in the playground though): https://go.dev/play/p/zyHA7khq-d8

On Saturday, August 10, 2024 at 7:35:00 PM UTC+2 lijh8 wrote:

I add nested tuple (slice) support:

    a := []any{"abc", 123, 3.14, 100, []any{"abc", 123, 3.14, 100}}
    b := []any{"abc", 123, 3.14, 100, []any{"abc", 123, 3.14, 100}}
    c, ok := tuple2.Cmp(a, b)
    fmt.Println(c, ok)


```

package tuple2

import (
    "cmp"
    "reflect"
)

func Cmp(a, b []any) (int, bool) {
    if len(a) != len(b) {
        return 0, false
    }

    for i := range a {
        if a[i] == nil || b[i] == nil {
            return 0, false
        }

        if _, boolean := a[i].(bool); boolean {
            return 0, false
        }
        if _, boolean := b[i].(bool); boolean {
            return 0, false
        }

        if a, b := reflect.TypeOf(a[i]), reflect.TypeOf(b[i]); a != b {
            return 0, false
        }

        if a, aOk := a[i].(string); aOk {
            if b, bOk := b[i].(string); bOk {
                if c := cmp.Compare(a, b); c != 0 {
                    return c, true
                }
            }
        }

        if a, aOk := a[i].(int); aOk {
            if b, bOk := b[i].(int); bOk {
                if c := cmp.Compare(a, b); c != 0 {
                    return c, true
                }
            }
        }

        if a, aOk := a[i].(float64); aOk {
            if b, bOk := b[i].(float64); bOk {
                if c := cmp.Compare(a, b); c != 0 {
                    return c, true
                }
            }
        }

        if a, aOk := a[i].([]any); aOk {
            if b, bOk := b[i].([]any); bOk {
                if c, ok := Cmp(a, b); ok && c != 0 {
                    return c, true
                } else if !ok {
                    return 0, false
                }
            }
        }
    }
    return 0, true
}

/*
func main() {
    a := []any{"abc", 123, 3.14}
    b := []any{"abc", 123, 3.14}
    c, ok := tuple2.Cmp(a, b)
    fmt.Println(c, ok)
}
*/

```

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/3163d798-23c4-48f9-947e-00dfc60d2791n%40googlegroups.com.

Reply via email to