Don't get me wrong here: Nim concepts introduce wonderful advantages; squarely among them:
1. Compiletime type checking of object variants matching on fields (considering that the runtime produces no stack trace on field access errors - this is nice) 2. Go-lang like interfaces 3. Many more things, far too advanced for present me Unfortunately, very much like {.base.} methods, a strange type of boilerplate is introduced: from math import PI,pow type ShapeKind = enum Circle,Rectangle ShapeProps = tuple[shape:string,area,perimeter:float] CircleShape = concept a a.r buildCircleProps(a) RectangleShape = concept a a.w a.h buildRectangleProps(a) Shape = object case kind:ShapeKind of Circle:r:float of Rectangle:w,h:float # Boilerplate start --> func buildCircleProps[T](ob:T):ShapeProps = discard func buildRectangleProps[T](ob:T):ShapeProps = discard # Boilerplate end func buildCircleProps(circle:CircleShape):ShapeProps = ($Circle,PI*circle.r.pow 2,2.0*PI*circle.r) func buildRectangleProps(rectangle:RectangleShape):ShapeProps = ($Rectangle,rectangle.w*rectangle.h,2.0*rectangle.w+2.0*rectangle.h) Run Nim is one of the least verbose languages I have encountered - which is a delight for someone that's been tortured by Java for years... But once in a blue moon I run into these very strange decisions. My thought was: incredible, Go-lang interfaces in Nim via concepts, the absolutely correct choice of technology! And then I realized that in Nim - of all languages - I had to go through example code on an obscure repo and write a novel to get there. What a shame... Any good reason for this (and {.base.} methods) other than bureaucracy?