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).