Были в немерле практически идеальные, template haskell тоже норм, скаловские и доттиевские макросы - в некоторых местах менее выразительны, но на порядки более эргономичны (в особенности те, что в дотти)
То есть, идеальный вариант, чтобы были доступны макросы как в немерле:
1. На этапе после лексера (как процедурные) 2. На этапе после парсинга (доступно человеческое AST) 3. На этапе после тайпчека (доступно AST со всеми типами)