The philosophy of mruby is to be a lightweight implementation of the Ruby ISO standard. These two objectives are partially contradicting. Ruby is an expressive language with complex implementation details which are difficult to implement in a lightweight manner. To cope with this, limitations to the “Ruby Compatibility” are defined.
This document is collecting these limitations.
This document does not contain a complete list of limitations. Please help to improve it by submitting your findings.
1/2
gives 0.5
¶ ↑Since mruby does not have Bignum
, bigger integers are
represented by Float
numbers. To enhance interoperability
between Fixnum
and Float
, mruby provides
Float#upto
and other iterating methods for the
Float
class. As a side effect, 1/2
gives
0.5
not 0
.
Array
passed to puts
¶ ↑Passing an Array to puts
results
in different output.
puts [1,2,3]
1 2 3
[1, 2, 3]
Kernel.raise
in rescue clause¶ ↑Kernel.raise
without arguments does not raise the current
exception within a rescue clause.
begin 1 / 0 rescue raise end
ZeroDivisionError
is raised.
No exception is raised.
mruby's Fiber
is implemented in a similar way to Lua's
co-routine. This results in the consequence that you can't switch
context within C functions. Only exception is mrb_fiber_yield
at return.
Array
does not support instance variables¶ ↑To reduce memory consumption Array
does not support instance
variables.
class Liste < Array def initialize(str = nil) @feld = str end end p Liste.new "foobar"
[]
ArgumentError
is raised.
For simplicity reasons no method visibility (public/private/protected) is supported. Those methods are defined but they are dummy methods.
class VisibleTest def public_method; end private def private_method; end end p VisibleTest.new.respond_to?(:private_method, false) p VisibleTest.new.respond_to?(:private_method, true)
false true
true true
The declaration form of following visibility methods are not implemented.
public
private
protected
module_function
Especially, module_function
method is not dummy, but no
declaration form.
module TestModule module_function def test_func p 'test_func called' end test_func end p 'ok'
ok
test.rb:8: undefined method 'test_func' (NoMethodError)
defined?
¶ ↑The defined?
keyword is considered too complex to be fully
implemented. It is recommended to use const_defined?
and other
reflection methods instead.
defined?(Foo)
nil
NameError
is raised.
alias
on global variables¶ ↑Aliasing a global variable works in CRuby but is not part of the ISO standard.
alias $a $__a__
nil
Syntax error
An operator can't be overwritten by the user.
class String def + end end 'a' + 'b'
ArgumentError
is raised. The re-defined +
operator does not accept any arguments.
'ab'
Behavior of the operator wasn't changed.
Kernel#binding
is not supported¶ ↑Kernel#binding
method is not supported.
$ ruby -e 'puts Proc.new {}.binding' #<Binding:0x00000e9deabb9950>
$ ./bin/mruby -e 'puts Proc.new {}.binding' trace (most recent call last): [0] -e:1 -e:1: undefined method 'binding' (NoMethodError)
mruby keyword arguments behave slightly different from CRuby 2.5 to make the behavior simpler and less confusing. Maybe in the future, the simpler behavior will be adopted to CRuby as well.
$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' [[{"a"=>1}], {:b=>2}]
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' trace (most recent call last): [0] -e:1 -e:1: keyword argument hash with non symbol keys (ArgumentError)
def m(a,(b,c),d); p [a,b,c,d]; end m(1,[2,3],4) # => [1,2,3,4]
Destructured arguments (b
and c
in above example)
cannot be accessed from the default expression of optional arguments and
keyword arguments, since actual assignment is done after the evaluation of
those default expressions. Thus:
def f(a,(b,c),d=b) p [a,b,c,d] end f(1,[2,3])
CRuby gives [1,2,3,nil]
. mruby raises
NoMethodError
for b
.
nil?
redefinition in conditional expressions¶ ↑Redefinition of nil?
is ignored in conditional expressions.
a = "a" def a.nil? true end puts(a.nil? ? "truthy" : "falsy")
Ruby outputs falsy
. mruby outputs truthy
.