1# Limitations and Differences 2 3The philosophy of mruby is to be a lightweight implementation of 4the Ruby ISO standard. These two objectives are partially contradicting. 5Ruby is an expressive language with complex implementation details which 6are difficult to implement in a lightweight manner. To cope with this, 7limitations to the "Ruby Compatibility" are defined. 8 9This document is collecting these limitations. 10 11## Integrity 12 13This document does not contain a complete list of limitations. 14Please help to improve it by submitting your findings. 15 16 17## `1/2` gives `0.5` 18 19Since mruby does not have `Bignum`, bigger integers are represented 20by `Float` numbers. To enhance interoperability between `Fixnum` 21and `Float`, mruby provides `Float#upto` and other iterating 22methods for the `Float` class. As a side effect, `1/2` gives `0.5` 23not `0`. 24 25## `Array` passed to `puts` 26 27Passing an Array to `puts` results in different output. 28 29```ruby 30puts [1,2,3] 31``` 32 33#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 34 35``` 361 372 383 39``` 40 41#### mruby [2.1.2 (2020-08-06)] 42 43``` 44[1, 2, 3] 45``` 46 47## `Kernel.raise` in rescue clause 48 49`Kernel.raise` without arguments does not raise the current exception within 50a rescue clause. 51 52```ruby 53begin 54 1 / 0 55rescue 56 raise 57end 58``` 59 60#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 61 62`ZeroDivisionError` is raised. 63 64#### mruby [2.1.2 (2020-08-06)] 65 66No exception is raised. 67 68## Fiber execution can't cross C function boundary 69 70mruby's `Fiber` is implemented in a similar way to Lua's co-routine. This 71results in the consequence that you can't switch context within C functions. 72Only exception is `mrb_fiber_yield` at return. 73 74## `Array` does not support instance variables 75 76To reduce memory consumption `Array` does not support instance variables. 77 78```ruby 79class Liste < Array 80 def initialize(str = nil) 81 @feld = str 82 end 83end 84 85p Liste.new "foobar" 86``` 87 88#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 89 90` [] ` 91 92#### mruby [2.1.2 (2020-08-06)] 93 94`ArgumentError` is raised. 95 96## Method visibility 97 98For simplicity reasons no method visibility (public/private/protected) is 99supported. Those methods are defined but they are dummy methods. 100 101```ruby 102class VisibleTest 103 104 def public_method; end 105 106 private 107 def private_method; end 108 109end 110 111p VisibleTest.new.respond_to?(:private_method, false) 112p VisibleTest.new.respond_to?(:private_method, true) 113``` 114 115#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 116 117``` 118false 119true 120``` 121 122#### mruby [2.1.2 (2020-08-06)] 123 124``` 125true 126true 127``` 128 129### Visibility Declaration 130 131The declaration form of following visibility methods are not implemented. 132 133* `public` 134* `private` 135* `protected` 136* `module_function` 137 138Especially, `module_function` method is not dummy, but no declaration form. 139 140``` 141module TestModule 142 module_function 143 def test_func 144 p 'test_func called' 145 end 146 147 test_func 148end 149 150p 'ok' 151``` 152 153#### Ruby [ruby 2.5.5p157 (2019-03-15 revision 67260)] 154 155``` 156ok 157``` 158 159#### mruby [2.1.2 (2020-08-06)] 160 161``` 162test.rb:8: undefined method 'test_func' (NoMethodError) 163``` 164 165## `defined?` 166 167The `defined?` keyword is considered too complex to be fully 168implemented. It is recommended to use `const_defined?` and 169other reflection methods instead. 170 171```ruby 172defined?(Foo) 173``` 174 175#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 176 177``` 178nil 179``` 180 181#### mruby [2.1.2 (2020-08-06)] 182 183`NameError` is raised. 184 185## `alias` on global variables 186 187Aliasing a global variable works in CRuby but is not part 188of the ISO standard. 189 190```ruby 191alias $a $__a__ 192``` 193 194#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 195 196` nil ` 197 198#### mruby [2.1.2 (2020-08-06)] 199 200Syntax error 201 202## Operator modification 203 204An operator can't be overwritten by the user. 205 206```ruby 207class String 208 def + 209 end 210end 211 212'a' + 'b' 213``` 214 215#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] 216 217`ArgumentError` is raised. 218The re-defined `+` operator does not accept any arguments. 219 220#### mruby [2.1.2 (2020-08-06)] 221 222` 'ab' ` 223Behavior of the operator wasn't changed. 224 225## `Kernel#binding` is not supported 226 227`Kernel#binding` method is not supported. 228 229#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)] 230 231``` 232$ ruby -e 'puts Proc.new {}.binding' 233#<Binding:0x00000e9deabb9950> 234``` 235 236#### mruby [2.1.2 (2020-08-06)] 237 238``` 239$ ./bin/mruby -e 'puts Proc.new {}.binding' 240trace (most recent call last): 241 [0] -e:1 242-e:1: undefined method 'binding' (NoMethodError) 243``` 244 245## Keyword arguments 246 247mruby keyword arguments behave slightly different from CRuby 2.5 248to make the behavior simpler and less confusing. Maybe in the 249future, the simpler behavior will be adopted to CRuby as well. 250 251#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)] 252 253``` 254$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' 255[[{"a"=>1}], {:b=>2}] 256``` 257 258#### mruby [mruby 2.1.2] 259 260``` 261$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' 262trace (most recent call last): 263 [0] -e:1 264-e:1: keyword argument hash with non symbol keys (ArgumentError) 265``` 266 267## Argument Destructuring 268 269```ruby 270def m(a,(b,c),d); p [a,b,c,d]; end 271m(1,[2,3],4) # => [1,2,3,4] 272``` 273Destructured arguments (`b` and `c` in above example) cannot be accessed 274from the default expression of optional arguments and keyword arguments, 275since actual assignment is done after the evaluation of those default 276expressions. Thus: 277 278```ruby 279def f(a,(b,c),d=b) 280 p [a,b,c,d] 281end 282f(1,[2,3]) 283``` 284 285CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`. 286 287## `nil?` redefinition in conditional expressions 288 289Redefinition of `nil?` is ignored in conditional expressions. 290 291```ruby 292a = "a" 293def a.nil? 294 true 295end 296puts(a.nil? ? "truthy" : "falsy") 297``` 298 299Ruby outputs `falsy`. mruby outputs `truthy`. 300