Remix.run Logo
whizzter 5 hours ago

If it wasn't built by Matz I'd have severe doubts, but it's clearly defined and I presume he knows all limitations of the Ruby semantics well.

My thesis work (back when EcmaScript 5 was new) was an AOT JS compiler, it worked but there was limitations with regards to input data that made me abandon it after that since JS developers overall didn't seem to aware of how to restrict oneself properly (JSON.parse is inherently unknown, today with TypeScript it's probably more feasible).

The limitations are clear also, the general lambda calculus points to limits in the type-inference system (there's plenty of good papers from f.ex. Matt Might on the subject) as well as the Shed-skin Python people.

eval, send, method_missing, define_method , as a non-rubyist how common are these in real-world code? And how is untyped parsing done (ie JSON ingestion?).

vidarh 3 hours ago | parent | next [-]

> If it wasn't built by Matz I'd have severe doubts, but it's clearly defined and I presume he knows all limitations of the Ruby semantics well.

It's a very pragmatic design: Uses Prism - parsing Ruby is almost harder than the actual translation - and generates C. Basic Ruby semantics are not all that hard to implement.

On the other extreme, I have a long-languishing, buggy, pure-Ruby AOT compiler for Ruby, and I made things massively harder for myself (on purpose) by insisting on it being written to be self-hosting, and using its own parser. It'll get there one day (maybe...).

But one of the things I learned early on from that is that you can half-ass the first 80% and a lot of Ruby code will run. The "second 80%" are largely in things Matz has omitted from this (and from Mruby), like encodings, and all kinds of fringe features (I wish Ruby would deprecate some of them - there are quite a few things in Ruby I've never, ever seen in the wild).

> eval, send, method_missing, define_method , as a non-rubyist how common are these in real-world code? And how is untyped parsing done (ie JSON ingestion?).

They are pervasive. The limitations are similar to those of mruby, though, which has its uses.

Supporting send, method_missing, and define_method is pretty easy.

Supporting eval() is a massive, massive pain, but with the giant caveat that a huge proportion of eval() use in Ruby can be statically reduced to the block version of instance_eval, which can be AOT compiled relatively easily. E.g. if you can statically determine the string eval() is called with, or can split it up, as a lot of the uses are unnecessary or workaround for relatively simple introspection that you can statically check for and handle. For my own compiler, if/when I get to a point where that is a blocking issue, that's my intended first step.

psychoslave 2 hours ago | parent [-]

Didn’t Ruby already embedded GCC at some point with similar ideas in mind?

vidarh 2 hours ago | parent [-]

Not embedding them, but mjit generated C and used a C compiler to compile it:

https://www.heroku.com/blog/ruby-mjit/#mjit

pantulis 3 hours ago | parent | prev | next [-]

> eval, send, method_missing, define_method , as a non-rubyist how common are these in real-world code?

Quite a lot, that's what allows you to build something like Rails with magic sprinkled all around. I'm not 100% sure, but probably the untyped JSON ingestion example uses those.

Remove that, and you have a very compact and readable language that is less strongly typed than Crystal but less metaprogrammable than official Ruby. So I think it has quite a lot of potential but time will tell.

shevy-java 4 hours ago | parent | prev [-]

> eval, send, method_missing, define_method , as a non-rubyist how common are these in real-world code

This depends on the individual writing code. Some use it more than others.

I can only give my use case.

.send() I use a lot. I feel that it is simple to understand - you simply invoke a specific method here. Of course people can just use .method_name() instead (usually without the () in ruby), but sometimes you may autogenerate methods and then need to call something dynamically.

.define_method() I use sometimes, when I batch create methods. For instance I use the HTML colour names, steelblue, darkgreen and so forth, and often I then batch-generate the methods for this, e. g. via the correct RGB code. And similar use cases. But, from about 50 of my main projects in ruby, at best only ... 20 or so use it, whereas about 40 may use .send (or, both a bit lower than that).

eval() I try to avoid; in a few cases I use them or the variants. For instance, in a simple but stupid calculator, I use eval() to calculate the expression (I sanitize it before). It's not ideal but simple. I use instance_eval and class_eval more often, usually for aliases (my brain is bad so I need aliases to remember, and sometimes it helps to think properly about a problem).

method_missing I almost never use anymore. There are a few use cases when it is nice to have, but I found that whenever I would use it, the code became more complex and harder to understand, and I kind of got tired of that. So I try to avoid it. It is not always possible to avoid it, but I try to avoid it when possible.

So, to answer your second question, to me personally I would only think of .send() as very important; the others are sometimes but not that important to me. Real-world code may differ, the rails ecosystem is super-weird to me. They even came up with HashWithIndifferentAccess, and while I understand why they came up with it, it also shows a lack of UNDERSTANDING. This is a really big problem with the rails ecosystem - many rails people really did not or do not know ruby. It is strange.

"untyped parsing" I don't understand why that would ever be a problem. I guess only people whose brain is tied to types think about this as a problem. Types are not a problem to me. I know others disagree but it really is not a problem anywhere. It's interesting to see that some people can only operate when there is a type system in place. Usually in ruby you check for behaviour and capabilities, or, if you are lazy, like me, you use .is_a?() which I also do since it is so simple. I actually often prefer it over .respond_to?() as it is shorter to type. And often the checks I use are simple, e. g. "object, are you a string, hash or array" - that covers perhaps 95% of my use cases already. I would not know why types are needed here or fit in anywhere. They may give additional security (perhaps) but they are not necessary IMO.