Raku Internals, History and Best Practices

55.1 How Rakudo Works

6model is the meta-object system underlying all types. MoarVM has a dynamic optimizer (spesh) that specializes code based on observed types, plus a JIT.

Precompilation: modules are compiled once to bytecode (.precomp directories) and reused.

Source → Grammar (Raku grammar written in NQP/Raku) → Actions → QAST (or RakuAST in the future) → Optimizer
       → Backend code generation → MoarVM bytecode (or JVM / JS)
MoarVM: JIT compiler, spesh (specializer: type specialization + inlining), generational GC, native threads, 6model object system
NQP ("Not Quite Perl"): a Raku subset used to bootstrap the compiler

55.2 History

Perl 6 announced by Larry Wall; RFC process begins Apocalypses, Exegeses, Synopses define the language

Pugs (Haskell implementation by Audrey Tang) boosts development

Rakudo on Parrot VM; Rakudo Star distributions begin (2010) MoarVM started

Perl 6.c ("Christmas") released: the first official language version

6.d ("Diwali") released: improved concurrency (non-blocking await), many refinements

Renamed to Raku; file extensions .raku, .rakumod, .rakutest

New dispatch mechanism, RakuAST work, 6.e preview features (use v6.e.PREVIEW), monthly Rakudo releases, zef ecosystem with fez

6.e is the next language version, previewable with use v6.e.PREVIEW (features such as new .snip, .skip with multiple values, is-monotonically-increasing, RakuDoc v2, and more; check the docs for the current list).

55.3 Best Practices

✅ Use my for lexical variables, typed signatures for public APIs, and subsets for validated domain values.

✅ Use kebab-case for subs, methods, and variables; CamelCase for types; UPPER-CASE for constants.

✅ Use say for debugging output, put for user-facing string output.

✅ Prefer roles for behavior reuse. Keep classes focused. Use TWEAK for validation.

✅ Use grammars for structured parsing instead of giant regexes, with action classes to build data.

✅ Use fail for recoverable errors in libraries and typed exceptions (X::MyApp::*) for exceptional cases.

✅ Use high-level concurrency (start/await, react/whenever, hyper).

✅ Write tests (t/*.rakutest) and Pod documentation, and use #| declarator docs.

✅ Specify :ver and :auth for dependencies in META6.json.

❌ Overusing Unicode operators where your team can't type or read them (ASCII equivalents exist for all of them)

❌ Overly clever meta-operator chains in maintained code ❌ Shared mutable state across threads without synchronization

❌ Using EVAL for configuration or untrusted data ❌ Confusing $ (item) and @ (list) containers: know when things flatten

❌ Forgetting that is compares with eq in tests (use is-deeply for structures)