Files
mruby-mruby/mrbgems/mruby-catch
Yukihiro "Matz" Matsumoto 31fea1709f gc.c: replace gcnext gray linked list with fixed-size gray stack
remove per-object gcnext pointer from MRB_OBJECT_HEADER, saving one
word (8 bytes on 64-bit) per object slot. the gray list for tri-color
marking is replaced by a fixed-size stack (MRB_GRAY_STACK_SIZE=1024)
in mrb_gc. when the stack overflows, a linear heap rescan recovers
gray objects.

object slot size: 48 -> 40 bytes (16.7% reduction on 64-bit).
benchmarks show up to 12% RSS reduction on object-heavy workloads
with neutral performance impact.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-12 13:38:21 +09:00
..
2020-10-12 18:20:07 +09:00
2025-06-08 17:00:07 +09:00

mruby-catch

This mrbgem provides catch and throw functionality similar to what is available in standard Ruby. It allows for non-local exits from blocks of code.

catch

The catch method is used to establish a block that can be exited prematurely using throw.

catch(tag) do |current_tag|
  # ... code ...
  if some_condition
    throw(tag, return_value)
  end
  # ... more code ...
end
  • With a tag: When catch is called with a tag (any Ruby object), it executes the block. If throw is called with the same tag from within this block (or any method called from within it), the catch block immediately exits and returns the value provided to throw.
  • Block completion: If the block executes to completion without throw being called with a matching tag, the catch block returns the result of the last expression evaluated in the block.
  • No tag: If catch is called without a tag, a new unique Object is created and used as the tag. This tag is passed as an argument to the block.
catch do |generated_tag|
  # generated_tag is a new Object
  throw(generated_tag, "hello")
end # => "hello"

throw

The throw method is used to initiate a non-local exit to a corresponding catch block.

throw(tag)
throw(tag, value)
  • With a tag and value: throw(tag, value) jumps to the innermost active catch block that is waiting for tag. The catch block then returns value.
  • With only a tag: throw(tag) is equivalent to throw(tag, nil).
  • Uncaught throw: If throw is called with a tag for which there is no matching catch block in the current call stack, an UncaughtThrowError is raised.

UncaughtThrowError

This is a custom error class that inherits from ArgumentError. It is raised when throw is called for a tag that is not currently being caught. It has two attributes:

  • tag: The tag that was thrown.
  • value: The value that was thrown with the tag.

Example

def check_value(val)
  puts "Checking: #{val}"
  if val < 0
    throw(:negative_value, val)
  elsif val == 0
    throw(:zero_value) # value will be nil
  end
  puts "#{val} is positive"
  val * 2
end

result = catch(:negative_value) do
  puts catch(:zero_value) do
    puts check_value(10)
    puts check_value(-5) # This will throw to :negative_value
    puts check_value(0)  # This would throw to :zero_value, but it's not reached
  end
  puts "This line is skipped if :zero_value is thrown."
end

puts "Result: #{result}"

# Output:
# Checking: 10
# 10 is positive
# 20
# Checking: -5
# Result: -5

puts "--- Next example --- "

result2 = catch do |tag_a|
  catch do |tag_b|
    puts "In tag_b block"
    throw(tag_a, "Exited from A via B")
    puts "This is not printed"
  end
  puts "This is not printed either"
end
puts result2 # => Exited from A via B