Style, Idioms and Best Practices
48.1 Official Style Guide (NEP-1) Highlights
2-space indentation, max ~80–100 columns.
camelCase for procs, vars, and fields. PascalCase for types. Enum values often have a prefix (pcFile, skCircle) unless {.pure.}.
Constants: camelCase or PascalCase. Avoid ALL_CAPS (except for C interop).
Prefer std/ import prefixes. Group imports.
nimpretty for formatting. --styleCheck:usages / error to keep identifier spelling consistent.
48.2 Idiomatic Nim
✅ Use let by default, var only when mutation is needed.
✅ Use result and implicit returns for short procs.
✅ Use UFCS for readable chains: data.filterIt(...).mapIt(...).
✅ Use value objects. Use ref only for shared or polymorphic data.
✅ Use openArray params, sink for consumed params, lent for borrowed returns.
✅ Use distinct types for domain safety.
✅ Use object variants for sum types. case statements must be exhaustive.
✅ Use Option/Result or tracked exceptions. Annotate raises on public APIs.
✅ Use runnableExamples in docs.
✅ Prefer procs → generics → templates → macros (least power).
❌ Don't catch Defects.
❌ Don't overuse converters.
❌ Don't overuse method or deep inheritance.
❌ Don't use {.cast(gcsafe).} to silence real thread-safety issues.
❌ Avoid global mutable state, especially with threads.
❌ Don't include when import works.
48.3 Project Hygiene
CI with GitHub Actions (jiro4989/setup-nim-action or iffy/install-nim), a matrix over Nim versions and operating systems.
Lock dependencies (nimble.lock). Semantic versioning. A CHANGELOG.
Tests with nimble test (unittest/unittest2). Docs published to GitHub Pages via nim doc.
Security: validate input, parameterize SQL, keep -d:release checks on for network-facing code, and fuzz parsers (libFuzzer via --passC:-fsanitize=fuzzer and the drchaos package).