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.

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

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

# 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

[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

# 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

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:

begin
  risky_operation
rescue => e
  log(e)
  raise e  # explicit re-raise required
end

Strings

"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:

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:

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:

# 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 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 for the complete list of configuration macros.