mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
256 lines
4.6 KiB
Markdown
256 lines
4.6 KiB
Markdown
# Limitations and Differences
|
|
|
|
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.
|
|
|
|
## Integrity
|
|
|
|
This document does not contain a complete list of limitations.
|
|
Please help to improve it by submitting your findings.
|
|
|
|
## `Kernel.raise` in rescue clause
|
|
|
|
`Kernel.raise` without arguments does not raise the current exception within
|
|
a rescue clause.
|
|
|
|
```ruby
|
|
begin
|
|
1 / 0
|
|
rescue
|
|
raise
|
|
end
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
`ZeroDivisionError` is raised.
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
`RuntimeError` is raised instead of `ZeroDivisionError`. To re-raise the exception, you have to do:
|
|
|
|
```ruby
|
|
begin
|
|
1 / 0
|
|
rescue => e
|
|
raise e
|
|
end
|
|
```
|
|
|
|
## Fiber execution can't cross C function boundary
|
|
|
|
mruby's `Fiber` is implemented similarly 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.
|
|
|
|
```ruby
|
|
class Liste < Array
|
|
def initialize(str = nil)
|
|
@field = str
|
|
end
|
|
end
|
|
|
|
p Liste.new "foobar"
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
`[]`
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
`ArgumentError` is raised.
|
|
|
|
## Method visibility
|
|
|
|
For simplicity reasons no method visibility (public/private/protected) is
|
|
supported. Those methods are defined, but they are dummy methods.
|
|
|
|
```ruby
|
|
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)
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
```
|
|
false
|
|
true
|
|
```
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
```
|
|
true
|
|
true
|
|
```
|
|
|
|
### Visibility Declaration
|
|
|
|
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.
|
|
|
|
```ruby
|
|
module TestModule
|
|
module_function
|
|
def test_func
|
|
p 'test_func called'
|
|
end
|
|
|
|
test_func
|
|
end
|
|
|
|
p 'ok'
|
|
```
|
|
|
|
#### Ruby [ruby 2.5.5p157 (2019-03-15 revision 67260)]
|
|
|
|
```
|
|
ok
|
|
```
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
```
|
|
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.
|
|
|
|
```ruby
|
|
defined?(Foo)
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
```
|
|
nil
|
|
```
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
`NameError` is raised.
|
|
|
|
## `alias` on global variables
|
|
|
|
Aliasing a global variable works in CRuby but is not part
|
|
of the ISO standard.
|
|
|
|
```ruby
|
|
alias $a $__a__
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
`nil`
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
Syntax error
|
|
|
|
## Operator modification
|
|
|
|
An operator can't be overwritten by the user.
|
|
|
|
```ruby
|
|
class String
|
|
def +
|
|
end
|
|
end
|
|
|
|
'a' + 'b'
|
|
```
|
|
|
|
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
|
|
`ArgumentError` is raised.
|
|
The re-defined `+` operator does not accept any arguments.
|
|
|
|
#### mruby [3.1.0 (2022-05-12)]
|
|
|
|
`'ab'`
|
|
Behavior of the operator wasn't changed.
|
|
|
|
## `Kernel#binding` is not supported until [3.0.0 (2021-03-05)]
|
|
|
|
`Kernel#binding` method is not supported.
|
|
|
|
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
|
|
|
|
```shell
|
|
$ ruby -e 'puts Proc.new {}.binding'
|
|
#<Binding:0x00000e9deabb9950>
|
|
```
|
|
|
|
## `nil?` redefinition in conditional expressions
|
|
|
|
Redefinition of `nil?` is ignored in conditional expressions.
|
|
|
|
```ruby
|
|
a = "a"
|
|
def a.nil?
|
|
true
|
|
end
|
|
puts(a.nil? ? "truthy" : "falsy")
|
|
```
|
|
|
|
Ruby outputs `truthy`. mruby outputs `falsy`.
|
|
|
|
## Argument Destructuring
|
|
|
|
```ruby
|
|
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:
|
|
|
|
```ruby
|
|
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`.
|
|
|
|
Keyword argument expansion has similar restrictions. The following example, gives `[1, 1]` for CRuby, mruby raises `NoMethodError` for `b`.
|
|
|
|
```ruby
|
|
def g(a: 1, b: a)
|
|
p [a,b]
|
|
end
|
|
g(a:1)
|
|
```
|