> allocChunk is an approach that enables users to customise their own allocator > types.
Are you sure this is necessary ? From my experience, the people who needs a custom allocator knows how to implement it and the people who don't know how to implement an allocator shouldn't touch that stuff anyway. There are very little use-case where you need a custom allocator. Plus, you're using dynamic dispatch when your memory allocator should certainly be fixed at compile-time. So, If you really want to do that, I would just use static dispatch or a compile-time switch and not bother with inheritance import std/streams type Chunk = ref object ChunkAllocator = ref ChunkAllocatorObj ChunkAllocatorObj = object MyStream = ref object of StreamObj al: ChunkAllocator proc allocChunk*(al: ChunkAllocator): Chunk {.base, raises: [], gcsafe.} = # RootEffect when not defined(MyStreamCustomAllocator): # doNormalAlloc(al) discard else: customAllocChunk(al) # user is expected to have implemented this function proc writeDataImpl(s: Stream, buffer: pointer, bufLen: int) = let s = MyStream(s) discard s.al.allocChunk() proc newMyStream(al: ChunkAllocator): MyStream = new (result) result.writeDataImpl = writeDataImpl Run