# mruby Language Features This guide describes the Ruby language features supported by mruby 4.0. mruby implements a subset of the Ruby language, optimized for embedded use. For a list of specific behavioral differences, see [limitations.md](../limitations.md). **If you are coming from CRuby**, note these major differences upfront: - No `require` or `load` — all code is linked at build time - No `defined?` keyword — use `respond_to?`, `const_defined?`, etc. - No refinements (`refine`, `using`) - No `Encoding` class — UTF-8 opt-in via `MRB_UTF8_STRING` - Fibers cannot yield across C function boundaries - Integer size varies by platform and boxing mode - Operators cannot be overridden by user code See [Key Differences from CRuby](#key-differences-from-cruby) for the full list. ## Syntax ### Keywords mruby supports the following keywords: `BEGIN`, `END`, `alias`, `and`, `begin`, `break`, `case`, `class`, `def`, `do`, `else`, `elsif`, `end`, `ensure`, `false`, `for`, `if`, `in`, `module`, `next`, `nil`, `not`, `or`, `redo`, `rescue`, `retry`, `return`, `self`, `super`, `then`, `true`, `undef`, `unless`, `until`, `when`, `while`, `yield` Magic variables: `__FILE__`, `__LINE__`, `__ENCODING__`, `__method__` **Not supported:** `defined?` (use `respond_to?`, `const_defined?`, etc. instead), `refinements` (`using`, `refine`). ### Classes and Modules ```ruby class Animal attr_accessor :name def initialize(name) @name = name end def speak "..." end end class Dog < Animal def speak "Woof!" end end module Greetable def greet "Hello, I'm #{name}" end end class Dog include Greetable end ``` All standard class and module features are supported: inheritance, `include`, `prepend`, `extend`, `attr_reader`/`attr_writer`/ `attr_accessor`, `public`/`private`/`protected` visibility, class variables (`@@var`), class methods, and `super`. ### Methods ```ruby # Required, optional, rest, post-rest, keyword, and block arguments def example(a, b = 1, *rest, last, key:, opt_key: nil, **kwargs, &block) end # Endless method definition def double(x) = x * 2 ``` ### Blocks and Procs ```ruby [1, 2, 3].each { |n| puts n } [1, 2, 3].each do |n| puts n end square = Proc.new { |x| x * x } square = proc { |x| x * x } double = lambda { |x| x * 2 } double = ->(x) { x * 2 } ``` ### Control Flow ```ruby # if/unless (both statement and modifier forms) if condition # ... elsif other # ... else # ... end result = value if condition result = value unless condition # case/when case obj when String then "string" when Integer then "integer" else "other" end # Loops while condition # ... end until condition # ... end for item in collection # ... end # Loop control break # exit loop next # skip to next iteration redo # restart current iteration retry # restart begin/rescue block ``` ### Exception Handling ```ruby begin risky_operation rescue ArgumentError => e handle_arg_error(e) rescue StandardError => e handle_error(e) ensure cleanup end raise "something went wrong" raise ArgumentError, "bad argument" ``` **Note:** `raise` without arguments in a `rescue` clause does not re-raise the current exception. Capture and re-raise explicitly: ```ruby begin risky_operation rescue => e log(e) raise e # explicit re-raise required end ``` ### Strings ```ruby "double-quoted with #{interpolation}" 'single-quoted literal' heredoc = <<~HEREDOC indented heredoc with #{interpolation} HEREDOC ``` ### Regular Expressions Regular expressions require an external gem such as `mruby-regexp-pcre` or `mruby-onig-regexp`. Without a regexp gem, `Regexp` literals (`/pattern/`) are not available. ### Pattern Matching (Limited) Only rightward assignment with simple variable binding is supported: ```ruby expr => var # assigns expr to var ``` `case/in` syntax, array/hash patterns, guard clauses, pin operator, find patterns, and alternative patterns are **not** supported. ## Numeric Types mruby's numeric type sizes depend on the boxing mode and platform. ### Integer | Configuration | Range | | -------------------------------------- | ---------------- | | 64-bit word boxing (default on 64-bit) | roughly +/- 2^62 | | 32-bit word boxing (default on 32-bit) | roughly +/- 2^30 | | NaN boxing (64-bit only) | -2^31 to 2^31-1 | Integer overflow raises a `RangeError` unless the `mruby-bigint` gem is included, in which case integers automatically promote to arbitrary precision. ### Float By default, `Float` uses 64-bit `double`. Compile-time options: - `MRB_USE_FLOAT32`: use 32-bit `float` instead - `MRB_NO_FLOAT`: disable floating-point entirely With word boxing on 64-bit, many float values are stored inline (without heap allocation) using a rotation encoding. ### Additional Numeric Types (via gems) - **Rational** (`mruby-rational`): exact rational arithmetic - **Complex** (`mruby-complex`): complex number support - **Bigint** (`mruby-bigint`): arbitrary-precision integers ## Core Classes These classes are always available in mruby (no gem required): | Class | Notes | | ------------- | -------------------------------------- | | Object | Base class for all objects | | Module | Module definition and mixin | | Class | Class definition and instantiation | | NilClass | Singleton `nil` | | TrueClass | Singleton `true` | | FalseClass | Singleton `false` | | Integer | Fixed-precision integer | | Float | Floating-point (unless `MRB_NO_FLOAT`) | | Symbol | Interned identifier | | String | Mutable byte string | | Array | Ordered collection | | Hash | Key-value mapping | | Range | Interval representation | | Proc | Closure / callable object | | Exception | Exception hierarchy root | | StandardError | Common error base | ### Core Modules | Module | Notes | | ---------- | ----------------------------------------- | | Kernel | Core methods (`puts`, `p`, `raise`, etc.) | | Comparable | Comparison operators via `<=>` | | Enumerable | Collection iteration methods | ## Standard Library (via gemboxes) mruby's standard library is organized into gemboxes. The `default` gembox includes all of the below. Use this table to find which gembox provides the class or feature you need: ### Classes and Modules | Class/Module | Gembox | Gem | | --------------------- | ---------- | ----------------- | | Fiber | stdlib | mruby-fiber | | Enumerator | stdlib | mruby-enumerator | | Enumerator::Lazy | stdlib | mruby-enum-lazy | | Set | stdlib | mruby-set | | ObjectSpace | stdlib | mruby-objectspace | | Time | stdlib-ext | mruby-time | | Struct | stdlib-ext | mruby-struct | | Data | stdlib-ext | mruby-data | | Random | stdlib-ext | mruby-random | | IO, File | stdlib-io | mruby-io | | Socket | stdlib-io | mruby-socket | | Dir | stdlib-io | mruby-dir | | Errno | stdlib-io | mruby-errno | | Math | math | mruby-math | | Rational | math | mruby-rational | | Complex | math | mruby-complex | | Bigint | math | mruby-bigint | | Method, UnboundMethod | metaprog | mruby-method | ### Methods and Features | Feature | Gembox | Gem | | ----------------------------- | ---------- | ------------------ | | `catch`/`throw` | stdlib | mruby-catch | | `Kernel#sprintf`, `String#%` | stdlib-ext | mruby-sprintf | | `Array#pack`, `String#unpack` | stdlib-ext | mruby-pack | | `Kernel#rand` | stdlib-ext | mruby-random | | `Kernel#eval` | metaprog | mruby-eval | | `Kernel#binding` | metaprog | mruby-binding | | `Proc#binding` | metaprog | mruby-proc-binding | | Runtime compiler | metaprog | mruby-compiler | ### Core Class Extensions The `stdlib` gembox also extends built-in classes with additional methods. These are included by default: | Extension | Examples | | ----------------------- | ---------------------------------------------- | | Array extensions | `#dig`, `#union`, `#difference` | | Hash extensions | `#dig`, `#transform_keys`, `#transform_values` | | String extensions | `#encode`, `#bytes`, `#chars` | | Numeric extensions | `Integer#digits`, `Integer#pow` | | Comparable extensions | `#clamp` | | Enumerable extensions | `#sort_by`, `#min_by`, `#max_by`, `#tally` | | Range extensions | `#size`, `#cover?` | | Proc extensions | `#<<`, `#>>` (composition) | | Symbol extensions | `#to_proc` | | Object extensions | `#then`, `#yield_self` | | Kernel extensions | `#__method__` | | Class/Module extensions | `Module#name` | ### Gembox Summary | Gembox | Contents | Notes | | ------------ | --------------------------------------------- | -------------------------------------------- | | `stdlib` | Core class extensions, Fiber, Enumerator, Set | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `stdlib-ext` | Time, Struct, Data, Random, sprintf, pack | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `stdlib-io` | IO, File, Dir, Socket, Errno | Requires stdio | | `math` | Math, Rational, Complex, Bigint | Works with `MRB_NO_STDIO` | | `metaprog` | eval, binding, Method, compiler | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `default` | All of the above + CLI tools | Full installation | ## Key Differences from CRuby ### No Runtime Loading mruby has no `require` or `load`. All code (gems, libraries) is linked at build time. To add functionality, include the appropriate gem in your build configuration: ```ruby MRuby::Build.new do |conf| conf.gem :core => "mruby-time" end ``` ### No `defined?` Keyword The `defined?` keyword raises `NameError` instead of returning a type string or `nil`. Use alternatives: ```ruby # Instead of: defined?(Foo) Object.const_defined?(:Foo) # Instead of: defined?(@var) instance_variable_defined?(:@var) # Instead of: defined?(method_name) respond_to?(:method_name) ``` ### Fiber Limitations Fibers cannot cross C function boundaries. You cannot yield from a fiber inside a C-implemented method. Only `mrb_fiber_yield` at function return is supported. ### Array and String Subclasses `Array` and `String` do not support instance variables to reduce memory. This means subclassing `Array` or `String` and adding `@fields` will raise an error. ### Operator Overriding Operators of primitive classes cannot be overridden by user code. Redefining `String#+` has no effect on the behavior of the `+` operator. ### Module Loading Hooks `include`/`prepend`/`extend` do not call `append_features`/ `prepend_features`/`extend_object` hooks. The module is included directly. ### Small Hash Optimization For small hashes, `#hash` is not called on keys. Custom `#hash` methods may not execute for small hash tables. ### No Refinements Module refinements (`refine`, `using`) are not supported. ### No Encoding Class There is no `Encoding` class. String encoding is either pure bytes or UTF-8 (opt-in via `MRB_UTF8_STRING` compile flag). ### `nil?` in Conditionals Redefining `nil?` has no effect on conditional expressions. The VM uses direct nil checks for performance. ### Integer Precision Integer size varies by boxing mode (see [Numeric Types](#numeric-types) above). Code relying on 64-bit integer precision may behave differently on 32-bit or NaN boxing configurations. ## Build-Time Configuration Key compile-time macros that affect language behavior: | Macro | Effect | | -------------------- | ---------------------------------- | | `MRB_NO_FLOAT` | Remove all float support | | `MRB_USE_FLOAT32` | Use 32-bit float instead of double | | `MRB_UTF8_STRING` | Enable UTF-8 string handling | | `MRB_INT32` | Force 32-bit integer | | `MRB_INT64` | Force 64-bit integer | | `MRB_STR_LENGTH_MAX` | Max string length (default 1MB) | | `MRB_ARY_LENGTH_MAX` | Max array length (default 2^17) | See [mrbconf.md](mrbconf.md) for the complete list of configuration macros.