Hacker News new | past | comments | ask | show | jobs | submit login
What's new in Ruby 3.1? (nithinbekal.com)
174 points by ksec on Jan 25, 2022 | hide | past | favorite | 48 comments



I kinda dig the new mapping syntax:

    { a:, b: } #=> { a: 1, b: 2 }
JS does it { a, b } and I find it very convenient, because if you code well, you usually have related things with the same name and repeating the name twice is just boilerplate.

Because of the set syntax in Python, the JS syntax can't work, but the ruby one would be nice.

Since Python keys can be anything, but usually are strings (and hence are quoted), I would probably invert the ":" though:

   { :a, :b }


I really like the ruby syntax. JavaScript now has the problem that it can't make code blocks expressions because it's ambiguous with object literal shorthand.


JavaScript has labels, so objects have always been ambiguous with blocks


Python will never have block expression, given how limited lambda is already, so that's not a concern.


It's not just because of the set syntax; it's also because Python dicts don't treat their keys as symbols, but rather evaluate them as expressions, whereas JS evaluates keys as symbols by default and requires `{[key]: val}` to evaluate them. So in Python you'd have to do something funky where `{a: a}` is `{value_of_a: value_of_a}`, but, say, `{a:}` is `{"a": value_of_a}`.


So its a shortcut that if you pass a variable as a key with no value it automatically creates a key with the same name as the variable and assigns the value?

That is kind of neat, but I tend to think of a bunch of {'a':a} as a bit of a code smell. Like maybe I should have used the hash/object/dict to begin with


It's mostly useful when a function generates values then return them as a dict or when things are parts in different chained calculations before being included in the dict to save lookups.


there is no way to achieve this in Python right? I miss this from js.


Nope.


Does anyone know if there's a tool out there similar to https://railsbump.org/ that would allow me to quickly check how many of the gems I depend on are compatible with ruby 3? I know ruby 3.0.x has been the recommended ruby version since rails 6.1, but I'm not sure if that means that a gem that is 6.1-compatible is necessarily also ruby 3 compatible (since rails 6.1 still supports ruby versions as old as 2.5.0)


Rust has spoiled me. I truly wish this was just built into bundler. I should be able to just update the version, run bundle install, and know what is supported.

Many dependencies have minimum, but not maximum versions specified. Most bugs have to be found at runtime (or via testing, which causes a runtime).

Again, Rust has spoiled me because if cargo build compiles, then it’s almost certainly ok.


Gems can already specify which version of Ruby they depend on: https://guides.rubygems.org/specification-reference/#require....

In practice you may not fully depend on it because people often write too permissive ranges (i.e. >= 2.7) and there has been some breaking changes between minor versions of Ruby 2.x so even if people write "~> 2.7" it may still be broken.


>I truly wish this was just built into bundler.

Interesting. Has anyone ever purposed this?


Picking up Ruby 3.0/3.1 after using 2.x for years is head spinning. Lots of new syntax to learn.

A lot of the syntax feels like hacks because Ruby syntax is rather permissive and finding pattens that don’t collide increasingly difficult.

Definitely has me a little grumbly, but I’ll get used to it eventually. Already loving _1.


For me I think there are only two major things happening between 2.5 let's say and 3.0:

- Keyword arguments - where there is no way around, you have to change them, upgrade gems...

- Everything else is optional. Code that is written in 2.5 mostly runs on 3.0

Also, I recently updated a Rails app from 2.7 to 3.0 and no code change is required.

I am asking as I am trying to use new syntax in my daily code so maybe I am missing something.

What is the new syntax that you discovered in 3.0 that made your head spin?


> Keyword arguments - where there is no way around, you have to change them, upgrade gems...

How does the keyword arguments change break old gems? I understood the new syntax to be optional in the case of not needing to repeat keys and values.



* RBS (Types)

* single line method definitions (def ... = ...)

* case...in

* pin operator

* rightward assignment (42 => int)

* use of the above to destruct arrays and hashes ( x => { b: foo } ; foo #=> 2 )


For RBS I don't yet have a case, but thank you for reminding me about single line definitions, case...in, and destructing arrays and hashes.

I should play a bit with them and see if they provide any help to write more readable code.


I usually do

    def red; “red”; end
The new syntax is a bit cleaner

    def red = “red”
But it looks too much like

    def color name = “red”
      name
    end


Im also not in love with the shorthand hash syntax, but besides `_1` I cant remember at the moment what new syntax 3.1 have that 2.0 dont. Pattern matching maybe?

But now that I think about it, yeah, even looking only at pattern matching there is a lot of new syntax going on.


I love how the idea of highlighting a specific part of the expression that can't be resolved jumped from one language to another within the last year or so and now the most common languages all support it.

(I remember node and python getting it but now can't find that in the release notes - I didn't imagine it, right?)


Python, I believe, is getting this feature in 3.11, which is due out in October. But the first 3.11 alpha release got some news talking about it:

https://docs.python.org/3.11/whatsnew/3.11.html


> the idea of highlighting a specific part of the expression that can't be resolved jumped from one language to another within the last year

CMUCL/SBCL must have supported this for decades.


I don't think Node does this. Maybe some test runners will do similar things to show expected vs actual in assertions?

Or maybe I'm just so numb to it and I don't recall properly.


As mentioned in further reading section, see also:

Comprehensive Ruby 3.1 changelog: https://rubyreferences.github.io/rubychanges/3.1.html


> IRB now supports autocomplete, and even shows the documentation when you tab through the options.

Oh this is pretty useful. How many times have I not wanted to learn about how to use a function. Showing the documentation when tabbing through the options can save me a lot of time browsing through the ruby docs. Looking forward to using this while working.

Good to see Ruby is still moving forward :)


What is a compelling use case for omitting values in hashes or method calls? I would think that it just increases cognitive load for the code maintainer, and makes the parser more complex.


Rust has had this bit of syntax sugar for a while now, it is used for structs. I think it's nice syntax, because it's located in a place where there's no doubt about the meaning. Both Rust structs and Ruby hashes are defined in-language as key-value sets, so whenever there's just one element instead of a pair, it's clear what the meaning is.


OCaml has it too! (for records)


With keyword arguments there are a lot of cases when we do things like

    def call(batch_id:, language: )
    end

    batch_id = find_batch_id_from_conditions(conditions)
    language = load_language_settings(user.id)

    call(batch_id: batch_id, language: language)
For me, I would gladly replace the last method with call(batch_id:, language:)


It removes the boilerplate of repeating the variable name when it's the same as the hash key. It's an extremely popular syntax in the JavaScript world bleeding over into Ruby. Personally, I enjoy it because it feels more fluid.


I don't like it either. I much prefer simple syntax with limited exceptions and variation. I use ruby every day but I prefer a syntax closer to go.


I have noticed that Ruby tends to move towards more magic which is true in this case.

I don't see any benefits at all from this.


I dont think a programming language can be _magic_ when talking about syntax. Syntax is something that one knows or dont know but no magic is there.

It is like saying limit in math is magic.

I could agree that we can evaluate if it is magic a library or a standard library.

More to the point: In the Ruby apps that I saw so far and articles I read I get a different feeling: more and more the community is promoting clarity, explicitness, simplicity.

I somehow feel that from Ruby 2 forward metaprogramming is seen as last resort. Almost no guideline promotes magic in Ruby code by default. More syntax is actually removing the need to do “magic tricks” with the language. It makes explicit in some cases some things that people were doing with DSLs.

I feel that magic was more present in Ruby 1.9 for example than now even if syntax was more limited. I was solving a lot of things with metaprogramming, monkey patching, calling private attributes and more. Now I will not approve my own code from back then if I will see it in an MR.


What's new in Ruby 3.1? Needless, opaque syntax "features" that will just confuse new programmers even more.


Other than existing code bases, what's the advantage of using Ruby for new projects these days when better tools exist? For example, Elixir - ergonomics of Ruby but cleaner functional approach, distributed and much faster for typical web apps.


Elixir certainly has its use case, but so does Ruby. Things like the huge amount of available gems and a big community, especially combined with a proven framework like Rails really makes it easy to build applications.

Elixir is well suited for a lot of things Ruby is but also has some shortcomings. For instance, the albeit growing community and available libraries is just not on the same level as Ruby. Furthermore the amount of available engineers knowing elixir can be a problem when hiring (ofcourse these can be trained internally) but in general hiring will be a tad bit harder.

Whilst I agree with you on the technical side (language is cleaner and obviously more performant) I do not agree on the statement dat Elixir is a better tool, as with a lot of things in software it depends.


I've had professional gigs spanning Ruby, Elixir, JS, C#, F#, and Python. I've found that Ruby is the most enjoyable to work with and has the easiest learning curve. It's a language that doesn't feel pretentious or dysfunctional, and most importantly of all, I can get shit done with it.


> better

Better is a very personal thing :) I like the ecosystem of ruby, always did and never had a reason to change.


Better is server bills that are 1/5 the cost, response times that are 3x faster and reduced complexity (no need for cache or background job servers). Don't get me wrong, I still really like and cut my teeth on Ruby, but there are better options for new projects now.


That's better performance, not better. Server bills is a pretty ridiculous metric to judge by; most of our server bills are due to the development kubernetes cluster (!), e.g our developers cost more in servers than our whole production setup. So what - should we go back to a monolith running locally then? Why use Elixir and not Go or Rust then if it's only performance you care about, Go has great concurrency and better general performance.


...and let's not forget that performance could be improved in newer versions so it's a bit tricky to say that A is faster than B, period. Particularly, in this new 3.1 version there is a new JIT (YJIT from Shopify guys) that shows up to 22% on railsbench, 39% on liquid-render. And there are alternative implementations like JRuby or GraalVM with diff. in performance.


That's why I said "other alternatives like Elixir". Go is one. Elixir syntax is comfortable (and productive) for Ruby devs and Phoenix for Rails folks. Use what you like.


> Use what you like

May I? Thanks!


I agree. I love ruby, it's my first love. I'd probably reach for Elixir/Phoenix for any new web app projects though.

At TuneCore we've already replaced a lot of our micro-services with Elixir/Phoenix/Broadway or Go and we've saved quite a bit of cash of server costs.


Wow at TuneCore, really? This is big.


We process billions of dollars a year, with 100s of billions of payments where the average payment is under a dollar.

Right tool for the right job and all that jazz.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: