One noteworthy thing is that in the `case` assuming each branch label emits a 
distinct type(like my package fungus does ) you can dispatch on those types
    
    
    type Shape = case
      of Circle: r: int
      of Triangle, Square: w, h: int
    
    proc area(circ: Circle): int = circ.r * circ.r * 4 # We're engineers
    proc area(tri: Triangle) int = tri.w * tri.h / 2
    proc area(square: Square): int = square.w * square.h
    proc area(shape:  Shape): int =
      #shape.unpackIt(area(it)) # The aforementioned macro is how one would 
really do this, but alas
      case shape
      of Circle:
        Circle(shape).area()
      of Triangle:
        Triangle(shape).area()
      of Square:
        Square(shape).area()
    
    var shapes = @[Shape Circle(r: 3), Square(w: 100, h: 20), Triangle(w: 100, 
h: 20)]
    
    for shape in shapes:
     echo shape.area()
    
    
    Run

Whereas in the the world with default case objects and aggressive checking the 
same logic would be
    
    
    type
      ShapeKind = enum Circle, Square, Triangle
      Shape = object
        case kind: ShapeKind
        of Circle: r: int
        of Square, Triangle: w, h: int
    
    proc areaCircl(shape: Shape): int =
      case shape.kind
      of Circle:
        shape.r
      else:
        raiseAssert false
    
    proc areaSquare(shape: Shape): int =
      case shape.kind
      of Square:
        shape.w * shape.h
      else:
        raiseAssert false
    
    proc areaTriangle(shape: Shape): int =
      case shape.kind
      of Triangle:
        shape.w * shape.h div 2
      else:
        raiseAssert false
    
    proc area(shape: Shape): int =
      case shape.kind
      of Circle:
        areaCircle(shape)
      of Square:
        areaSquare(shape)
      of Triangle:
        areaTriangle(shape)
    
    
    Run

Whilst the former is syntax sugar on the latter one does not have to always 
have a `case` statement before accessing fields. Practically it removes runtime 
checks before access. Which I'd argue is just better as it means fields are a 
type operation away. If you want to have better static typing it seems like a 
no brainer to embrace a distinct type per branch as it removes ambiguity and 
means you only need runtime checks on write and conversion, no amount of 
aliasing through procedure parameters makes `Circle` lose the `Circle` type 
unless you pass it to a`Shape`.

Reply via email to