A good type system for Ruby is very much needed. Matz himself has stated that a type system is very much on the horizon for Ruby. Can't wait.
Scala 3 is doing the typed AST thing, so hell, why not?
The problem is that the ruby execution model is fundamentally incompatible with ahead-of-time compilation without making a lot of decisions about what occurs before compilation and what is deferred until later. E.g. a lot of Ruby programs execute code to determine which files to "require" (e.g. iterating over all files in a directory is a common pattern). In some cases that is a convenience for developers. In others it's meant to e.g. provide "plugin" abilities at runtime. In both cases the included code can totally change the behaviour of large parts of your code base.
Those decisions are possible to make, but you must make them and you probably can't make them satisfactorily without providing a mechanism for the developers to specify intended behaviour. If your decision is to defer everything until after compilation, you'll basically end up JIT-compiling most of the code at runtime, and all type information from before that point is suspect.
I think for this to be tractable you'd basically have to implement a complete Ruby interpreter in Crystal and then transpire the Ruby program to bytecode to be run by the Crystal interpreter. So not really a meaningful or useful transpilation any more, and certainly not fast.
Even basic things like method dispatch do not have the same semantics in Crystal as in Ruby, so almost nothing could be tarnspiled 1-to-1.
Even a small subset of ruby being transpiled would be a useful thing for some developers.
You're much more aware of some of the constraints here than I am, as Oracle doesn't pay me to hack ruby for a living.
With a typed AST, there'd be enough information there to build a foundation for a rb2cr tool. I didn't say the two languages are best friends and it'll be a breeze.
Most of the ruby code I want to rescue isn't littered with string-based define_method nonsense. Most of ruby I think worth saving at all is outside of rails and exists in various tools or maybe some metasploit modules or stuff like that. The pieces of code that utilize the grossest dynamic elements of ruby, like define method or objectspace, that stuff doesn't need to survive.
Even getting 50% of a codebase in ruby compiled to reasonable crystal is a much better foundation than previously purported successors (elixir, scala, swift) can do.
If ruby gets a typed ast, I'll try and write a simple transform tool for the simplest ruby.
I see what you are saying - but this is where the issue is I think. You may not write code that does sophisticated metaprogramming, but the gems you use are probably fundamentally based on it. Even just requiring some of the standard library uses a surprising amount of of metaprogramming. For example you can't load something as basic as 'fileutils' without doing a lot of metaprogramming.
The entire Ruby ecosystem is built on metaprogramming.
I really appreciate your thought on this! I look up to your work a lot. Sometimes I wish I had spent my career with compiler a instead of disassemblers...
Yes, there will be a lot of ruby that can never by crystallized. Yes that kinda sucks. So yes it's very good to explore optional or gradual for incremental refactors and modernization. But if even 1% of ruby code CAN be crystallized, then it's worth it to do it. Maybe not for you, but my time isn't nearly as expensive as yours must be, so I understand your reasoning here I think.
I don't mean to be adversarial here.
If people are happy to use a subset of Ruby then yes it could be transpiled. But a simple subset of Ruby should work great in the new JIT compilers we're getting anyway, without using Crystal.
I don't and have never used the vast majority of Ruby's metaprogramming features, but I'm the odd duckling in an equation where probably 95% or more Ruby programmers are Rails programmers, and I am not. I mean, I can, but I don't. That factor makes less sympathetic to the majority of Ruby users who won't have any stake in a project like what I'm thinking about. And that's ok. And either way, if they want to make use of all those features then they will or maybe already have realized that Ruby already does what they want and Ruby3's care for backwards compat surely will cater to that majority in order to keep them on board. Metaprogramming I think is the primary style of Ruby, and that's OK.
The Crystal team has essentially reprogrammed the way I think about how it should feel to write good OO code. Scala did the same thing for a time, but just the sheer pain of SBT drove me away. With Crystal, Having parametric modules is an incredible advantage. I can write mixins essentially like traits that specialize on some new type in my program.
I have to consider how my methods end up typing out, and that changes the way I think about how I'm going to get from here to there. With Ruby, I really like that left-to-right idea of chaining until I arrive at the structure I want, and the more Crystal I write the more I realized how irritating it was to hunt down Ruby bugs by:
whatever.tap{ |o| puts "#{o} is a: #{o.class} here" }
or even deeper with responds_to? or whatever I'm trying to figure out. With crystal, all I have to do is look at the stacktrace, it is getting a nil where it shouldn't be at SomeClass#some_method on line 230842349, and I immediately can work on the bug at the source of it, instead of the tedious extra step of finding it.
Being able to make Ruby do magic was never part of the equation that held me a romantic captive to Ruby, it was always the succinctness. Elixir came close, but Crystal gets me all the way there.
If nothing else, maybe I will learn something new trying to find a subset of ruby3 that I can transpile.
I haven't read much about the new JIT, but if you're happy about it, maybe I should stop procrastinating and find out about it.
That said, you can't always expect sensible or human-brain-friendly results if you're moving between two languages that work very different.
In practical terms, people respond much better to having their egos stroked than they do to being told they're wrong. Evidence and logic work much better when someone doesn't feel like their ego is at stake. Telling someone they're right before pointing out that they could be more right is one way to do this. Telling people that they're wrong is more likely to provoke a defensive reaction and a closed mind than it is genuine thoughtfulness and consideration. We've all seen people refuse logic, reason, and evidence because they feel personally attacked, I suspect.
This is a lesson I gleaned from the (in)famous "How To Make Friends And Influence People". It's not wrong, it's just cynical.
So of course it's insincere. Human interaction is greased with little insincerities. It's how we deal with egos.
I'm sincere in that I want people to listen to my points without getting their egos in the way.
This may surprise you, but I really wish my experience agreed with you. I really wish most people saw immediately through insincerity and ego-stroking and empty complements. Indeed, some do.
Most of the time, it's disturbingly effective. My data to date suggests that most people won't look too closely when you feed them kind words to hide the others.
Just my two cents, not parent btw
It's definitely a threat though. The Amber Framework is very familiar to people who know Phoenix or Rails.
Personally, coming from Ruby, Crystal has a slightly steeper learning curve. However, I feel that magic spark deep down now that I've spent more time with it and I'm more aware of what inference can do and how to use it for my benefit.
Little safety things that seem irritating at first, but then you put the pieces together and understand them a bit more.
T | Nil is a culprit here. It seems obnoxious, but then you realize, I can just chain methods in a case statement, I don't have to check for nil over and over, just in the topmost part of whatever code it is. It's not how I normally think, and my instinct was wrong based on my initial understanding, but now I'm much more comfortable with it.
As for tooling, Crystal is rather weak. This too will come with time.
And it's really useful for CLIs and APIs.