0

What is idiomatic pattern for TclOO object equals implementation?

Perhaps compare concatenated sorted lists of all properties?

Are there analogs to Scala case classes?

Andrei Pozolotin
  • 897
  • 3
  • 14
  • 21

1 Answers1

1

TclOO defines no equality system for you by design; as the objects are in general modifiable, there's no automatic notion that would apply other than object identity, and you can just compare the name of the object to get that (or the results of info object namespace $theObj, if you're being very paranoid; I think Tcl 8.7 will provide more options, but that's not yet accepted).

If you want to define an equality system such as you are proposing, you could do this:

oo::class create PropertyEquals {
    method equals {other} {
        try {
            set myProps [my properties]
            set otherProps [$other properties]
        } on error {} {
            # One object didn't support properties method
            return 0
        }
        if {[lsort [dict keys $myProps]] ne [lsort [dict keys $otherProps]]} {
            return 0
        }
        dict for {key val} $myProps {
            if {[dict get $otherProps $key] ne $val} {
                 return 0
            }
        }
        return 1
    }
}

Then you just need to define a properties method on the class you might be comparing, and mix in the equals method from the above.

oo::class create Example {
    mixin PropertyEquals
    variable _x _y _z
    constructor {x y z} {
        set _x $x; set _y $y; set _z $z
    }
    method properties {} {
        dict create x $_x y $_y z $_z
    }
}

set a [Example new 1 2 3]
set b [Example new 2 3 4]
set c [Example new 1 2 3]
puts [$a equals $b],[$b equals $c],[$c equals $a]; # 0,0,1

Note that Tcl doesn't provide complex collection classes like some other languages (because it has array-like and mapping-like open values) and so doesn't need an object equality (or content hashing) framework to support that.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • good to know, thank you. we are also considering using by-product of `yaml` class serialization, and mapping `equals -> toYAML` – Andrei Pozolotin May 18 '18 at 22:38
  • One thinks that code borrowed from `Tcl_CopyObjectInstance` could be used to set up a similarly-scoped equivalence predicate. – Peter Lewerin May 19 '18 at 09:13
  • @AndreiPozolotin Any mechanism that defines a meaningful equality is fine; the only tricky thing is that there's no default. If there was a default, it'd probably use `info object creationid` which is part of [TIP #500](https://core.tcl.tk/tips/doc/trunk/tip/500.md) and is the value used for internal comparisons (for cache management, so not really script-exposed). – Donal Fellows May 19 '18 at 12:23
  • @DonalFellows flexibility is great, yet perhaps inclusion of `value objects` based on `case classes` into TclOO by default would make things more simple (provied `equals`, `property methods`, `toString` or `toYaml`, clean `with clone`, etc) https://stackoverflow.com/questions/2312881/what-is-the-difference-between-scalas-case-class-and-class – Andrei Pozolotin May 19 '18 at 14:09
  • Why the need for a `properties` method, why not a generic (default) implementation using `info object variables|vars`, provided by the mixin? It is certainly fine to allow a developer to refine an equality protocol, but in the general case introspection can come to rescue ... – mrcalvin May 22 '18 at 13:01