With πŸ’Ž Ruby 3 released, let's have a look at how the language evolved since the version 2.0 was released more than 7 years ago. A history thread about #ruby #ruby3 🧡:
In 2013 @yukihiro_matz announced Ruby 2.0 and he said the core team would release a new minor version every year during Christmas timeπŸŽ„This was huge news πŸŽ‰ for Ruby devs since until then the releases were irregular. It made the future look very bright
Ruby 2.0 brought a bunch of features: keyword arguments, module#prepend and lazy enumerators.
One minor, but verys useful feature was %i literal to create arrays of symbols - I use it so often! πŸ’ͺ🏻
Another important thing were refinements - a somewhat controversial feature that app developers might not use very often, but that can be found in some libraries. πŸ€”

@nusco made a great talk about refinements back in 2015:
A notable thing is that Ruby 2.0 was very easy to migrate to. While it was not 100% backwards compatible with Ruby 1.9, I can't remember any major issues when migrating
Ruby 2.1 (released in 2013) didn't introduce major visible features, but improved performance and memory management a lot. Introducing generational GC was a big thing and I remember watching @_ko1 talks about it and thinking it's a fascinating concept (rubykaigi.org/2013/talk/S73/) 🀯
Oh, I almost forgot - freezing strings! "my text".freeze now allowed developers to improve memory usage, as lots of strings are never modified
Ruby 2.2 (2014) further improved on speed and memory. Incremental GC reduced pause time and and finally covered symbols as well (until then symbol, once allocated, stayed in memory forever, causing some devs a lot of headache)
An interesting addition was improving on hash syntax. Until then it didn't work with symbols containing dashes. In 2.2 you could write { "my-symbol": "x" }

It introduced some confusion as the key looks like a string, while it's actually a symbol 🀨
2015 brought us Ruby 2.3 and if IIRC announcement of Ruby 3x3 initiative that promised Ruby 3 would be 3x faster than Ruby 2.0 🀩
I guess the most controversial feature of Ruby 2.3 was the "lonely operator" - calling object&.method now would not throw an error if object was nil. That allowed a "safe" method chaining β›“
IIRC this operator was inspired by "try" method introduced in Rails. And so were Array#dig and Hash#dig methods: it's so good to see some useful methods from #rubyonrails being introduced directly to the language itself
We're now in 2016 and Ruby 2.4. A big change here was unifying 2 data types: Fixnum and Bignum into a single Integer class. This caused some compatibility issues, but overall was a great step - until then above certain numbers, Fixnum automatically became Bignums
Ruby 2.4 also added binding.irb - it was possible to run a REPL inside your process without having to use external libraries like pry (although pry and later byebug still provided useful functionality) 🀩
Needless to say, version 2.4 introduced further performance improvenents and brought us closer to Ruby 3.0
December 2017 and Ruby 2.5 - a bunch of really useful stuff here: yield_self function, pattern support in Enumerable predicates, Hash#slice (inspired by Rails or am I wrong here?) and reversing stack trace order for easier debugging
One change that I didn't rely on much, but that could be significant for some people was support for rescue and ensure keywords were supported inside do/end blocks
And one of my favorites - Hash#transform_keys, really useful little functions that I had to implement myself in a bunch of applications πŸ˜…
Damn, we're at like 20 tweets here and I think I miss a lot of stuff on the way. Let me know if there's something critical that I'm skipping here!
Ok, 2018, Ruby 2.6 - and experimental JIT. This. Was. Huge! πŸ’₯🧨 yes, I know, the JIT is still not in its final form and there's a lot to improve there, but really, hard to emphasize that change enough.
From official Ruby site - some benchmarks showed 1.7x performance improvements with JIT enabled.
2.6 also brought a bunch of new functions - "then" (which is really an alias of "yield_self" but sounds way cooler), endless ranges, support for non-ascii capital characters (to name constants - still you can't name a class with just an emoji though ☹️)
That's also when Bundler became part of the standard library - btw raise your hand πŸ‘‹πŸ» if you still remember how otugh were our lives pre-Bundler πŸ˜…. The work @wycats and others did was just amazing. It was great to finally see Bundler becoming a part of stdlib
With Ruby versions around 2.5 and further, people started asking questions about the final form of Ruby 3. I remember @yukihiro_matz saying "when we achieve our goals, we will just name the next version 3.0" and I loved that answer πŸ˜„
Ok, we're almost done and Twitter tells me I can't keep adding more tweets right now, so I'm going to throw this out into the world and continue with Ruby 2.7
2019, just 1 year ago we saw Ruby 2.7 and another amazing (yet still experimental) feature - pattern matching. Seriously, having a proper pattern matching built into the language is a game changer. It's one of the things that made me love #elixir
Pattern matching in Ruby reuses "case" keyword, it just makes it way more powerful πŸ’ͺ🏻
Quite a difficult thing was fixing keyword arguments - remember, they were brought a few years ago, but they were not fully baked, as you could just pass a hash instead and it was decomposed into keyword args
It was difficult as a lot of people relied on this behaviour, but I believe it was badly needed - the mixing between hash and keyword arguments was very complex. More here: ruby-lang.org/en/news/2019/1…
Another new feature were numbered parameters - calling a block with passed params now did not require giving them explicit names. I'm still not sure how I feel about this one.
A funny little change - calling private method was now allowed with explicit usage of "self" - until then calling "self.private_method" would raise an error

Lastly - forwarding arguments by using (...) - honestly I haven't used it myself yet, any opinions about it?
Ok, and here we are - December 2020 and Ruby 3.0, with a delivered promise of 3x speed improvement against version 2.0.
There are ton of new stuff in version 3: Ractor that opens a completely new world for concurrent execution in Ruby, JIT improvements that put it on track to become a standard way to run Ruby apps soon
Static typing - another huge thing that deserves its own article or even a series. I can't give it enough justice in a tweet.
And these are just the major things - there's much, much more than that. Even though I don't work with Ruby so often anymore, I'm truly excited about its future. The way it evolved over the last 7 years is absolutely amazing.
Thank you @yukihiro_matz and all the contributors for making it happen! πŸ™‡β€β™‚οΈ

β€’ β€’ β€’

Missing some Tweet in this thread? You can try to force a refresh
γ€€

Keep Current with Gregory Witek πŸŽ₯ ⌨️

Gregory Witek πŸŽ₯ ⌨️ Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!