[HN Gopher] Ruby 4.0.0
___________________________________________________________________
Ruby 4.0.0
Author : FBISurveillance
Score : 658 points
Date : 2025-12-25 04:13 UTC (18 hours ago)
(HTM) web link (www.ruby-lang.org)
(TXT) w3m dump (www.ruby-lang.org)
| aaronbrethorst wrote:
| It wouldn't be Christmas without a new version of Ruby. Thanks
| Matz and co!
| nish__ wrote:
| Ruby::Box looks useful.
| shevy-java wrote:
| Right now it is just the foundation I guess. That is, more work
| to be put on top of it. byroot kind of pointed that out that
| the proposal reminds him of containers and I think this is the
| long-term goal eventually, e. g. namespaced isolated
| containers. At a later time, I think, the syntax for
| refinements may be simplified and also be integrated into
| Ruby::Box, since Ruby::Box is kind of a stronger refinement in
| the long run. But that's my take; ultimately one has to ask
| matz about the changes. What he did say on the bugtracker was
| that this is to be considered a low-level API e. g. a
| foundation work. So things will be put on top of that
| eventually.
| desireco42 wrote:
| This really makes Christmas festive. I don't think I need new
| features, but sure love simplicity of 4.0.
|
| I am installing it now. Thank you Matz and team.
| ekvintroj wrote:
| My best Christmas gift <3 Love you Ruby.
| ksec wrote:
| It seems Ractor is still work in progress while Fiber has matured
| a lot in the last few releases.
|
| I vaguely remember reading Shopify is using Fiber / Rack / Async
| in their codebase. I am wondering if Rails will get more Fiber
| usage by default.
| shevy-java wrote:
| To me it seems very few people use ractors. A bit more use
| fibers though.
|
| It's a bit of a mess IMO. I'd much prefer everything be
| simplified aggressively in regards to threads + GIL; and
| Ractors integrated on top of Ruby::Box to provide not only
| namespaced container-like entities but also thread-support as a
| first-class citizen at all times. The API of ractors is weird
| and really not fun to use.
| Lammy wrote:
| I really enjoyed using them for my Ruby file-matching library
| where I wanted to read `shared-mime-info` XML source package
| files directly and on the fly as opposed to using the pre-
| processed secondary files that the upstream `update-mime-
| database` tool spits out. The problem is that a type
| definition can be spread out over multiple XML packages in
| both system and user paths, so the naive implementation of
| reading them all at once wastes a massive amount of memory
| and a massive number of object allocations (slow) when most
| people use maybe 5% of the full set of supported types (the
| JPEGs and HTMLs and ZIPs of the world).
|
| I wanted to read the source package files directly because I
| always found `shared-mime-info`'s usual two-step process for
| adding or editing any of the XML type data to be annoyingly
| difficult and fragile. One must run `update-mime-database` to
| decompose arbitrarily-many XML packages into a set of
| secondary files, one all-file-extensions, one all-magic-
| sequences, one all-aliases, etc. System package managers
| usually script that step when installing software that come
| with their own type data. I've accidentally nuked my entire
| MATE session with `update-mime-database` before when I wanted
| to pick up a manual addition and regenerated the secondary
| files while accidentally excluding the system path that had
| most of the data.
|
| I ended up doing it with four Ractors:
|
| - a Ractor matching inputs (MIME Type strings, file
| extensions, String or Pathname or URL paths for sniffing)
| against its loaded fully-formed type definition objects.
|
| - a Ractor for parsing MIME Type strings (e.g.
| "application/xml") into Hash-keying Structs, a task for which
| the raw String is unsuitable since it may be overloaded with
| extra syntax like "+encoding_name" or fragment ";key=value"
| pairs.
|
| - a fast XML-parser Ractor that takes in the key Structs
| (multiple at once to minimize necessary number of passes) and
| figures out whether or not any of those types are defined at
| all, and if so in which XML packages.
|
| - a slow XML-parser Ractor that takes the same set of
| multiple key Structs and loads their full definition into a
| complete type object, then passes the loaded objects back to
| the matcher Ractor.
|
| The cool part of doing it this way is that it frees up the
| matcher Ractor to continue servicing other callers off its
| already-loaded data when it gets a request for a novel type
| and needs to have its loader Ractors do their comparatively-
| slow work. The matcher sets the unmatched inputs aside until
| the loaders get back to it with either a loaded type object
| or `nil` for each key Struct, and it remembers `nil`s for a
| while to avoid having to re-run the loading process for
| inputs that would be a waste of time.
|
| The last pre-Ractorized version allocated around 200k objects
| in 7MiB memory and retained 17k objects in 2MiB of memory for
| a benchmark run on a single input, with a complete data load.
| The Ractorized version was twice as fast in the same
| synthetic benchmark and allocated 20k objects in 2MiB of
| memory and retained 2.5k objects in 260KiB of memory for its
| initial minimal data load. I have it explicitly load
| `application/xml` and `application/zip` since those combined
| are the parent types for like a third of all the other types,
| and a few other very common types of my choosing.
|
| I think a lot of the barrier to entry for Ractors isn't the
| API for the Ractors themselves but in figuring out how to
| interact with Ractorized code from code that hasn't been
| explicitly Ractorized (i.e. is running in the invisible
| "main" Ractor). To that end I found it easiest to emulate my
| traditional library API by providing synchronous entry-point
| methods that make it feel no different to use than any other
| library despite all the stuff that goes on behind the scenes.
| The entry methods compose a message to the matcher Ractor
| then block waiting for a result or a timeout.
|
| I also use Ractors in a more lightweight way in my UUID/GUID
| library where there's a Ractor serving the incrementing
| sequence value that serves as a disambiguator for time-based
| UUIDs in case multiple other Ractors (including invisible
| "main") generate two UUIDs with the same timestamp. Speaking
| of which, I'm going to have to work on this one for Ruby 4.0,
| because it uses the removed `Ractor.take` method.
| byroot wrote:
| > It seems Ractor is still work in progress
|
| The Ractor experimental status could almost be removed. They no
| longer have known bugs, and only one noticeable performance
| issue left (missing Ractor local GC).
|
| But the API was just recently changed, so I think it's better
| to wait another years.
|
| > I vaguely remember reading Shopify is using Fiber / Rack /
| Async in their codebase.
|
| Barely. There is indeed this management obsession for fibers
| even when it doesn't make sense, so there is some token usage
| there and there, but that's it.
|
| There is one application that was converted from Unicorn to
| Falcon, but falcon isn't even configured to accept concurrent
| requests, the gain is basically 0.
|
| As for Rails, there isn't much use cases for fibers there,
| except perhaps Active Record async queries, but since most
| users use Postgres and PG connections are extremely costly, few
| people are using AR async queries with enough concurrency for
| fibers to make a very noticeable difference.
| ksec wrote:
| I just search for the tweet again and it state [1] "Falcon is
| now serving most of Shopify storefront traffic: web and
| API.", or is that an out of context quote?
|
| [1] https://x.com/igrigorik/status/1976426479333540165
| byroot wrote:
| I know that tweet, it's real, but that doesn't contradict
| my comment.
|
| They indeed replaced Unicorn by Falcon in one application,
| but falcon is configured in "Unicorn mode" (no concurrent
| requests). So the gain is effectively 0.
|
| Also note how they don't share any performance metrics,
| contrary to https://railsatscale.com/2023-10-23-pitchfork-
| impact-on-shop...
| ksec wrote:
| Thanks. That makes more sense.
| mikestorrent wrote:
| Still love Ruby deeply even though I now work somewhere where
| it's not in use. Thanks for the release, I hope I find a reason
| to use it!
| andrewinardeer wrote:
| It truly is Christmas.
| ergocoder wrote:
| I haven't looked at Ruby for a long time. I've moved away due to
| the lack of typing. Any degree of typing would be helpful. Does
| it support typing yet?
| riffraff wrote:
| There's an official format for defining types in separate files
| (RBS) and some tooling to type check them (matz doesn't like
| types next to the source code).
|
| There's a pretty battle tested tool to define inline types as
| ruby syntax and type check both statically and at runtime[0].
|
| It's still not a particularly nice situation imvho compared to
| typescript or python, but there's been some movement, and
| there's a newsletter that follows static typing developments
| [1] which may give you some insights.
|
| 0: https://sorbet.org/
|
| 1: https://newsletters.eremin.eu/posts
| adamors wrote:
| I've used Sorbet on a project for 2 years recently and it
| honestly was the final nail in the coffin for Ruby for me.
|
| Really rough around the edges, lots of stubs have to be added
| because support for gems is lackluster but whatever Sorbet
| generates are hit or miss etc. So you end up writing a lot of
| hard to understand annotations and/or people get frustrated
| and try to skip them etc.
|
| Overall a very bad DX, compared to even typed Python. Don't
| even want to compare it to TS because then it becomes really
| unfair.
| vmware513 wrote:
| Unfortunately, the type support is still useless. I abandoned
| Ruby for the same reason, and it is still relatively slow and
| eats a lot of memory.
| dismalaf wrote:
| It's literally faster than Python but ok.
| morcus wrote:
| Is being faster than Python considered to be a notable
| feature?
| gkbrk wrote:
| Python is one the most popular programming languages.
| Ruby fits into a similar category as Python (high level,
| interpreted scripting language, very dynamic, has a rich
| ecosystem with tons of existing code). Being faster than
| Python makes it more attractive to use, or port Python
| codebases to.
| wiseowise wrote:
| Nobody cares about Ruby outside of RoR
|
| Python is one of the Lingua Franca of scientific, data,
| and most importantly, ai communities
|
| Has much bigger community than Ruby
|
| Has much, much better tooling story
|
| Has much better gradual typing story
|
| Isn't THAT much slower than Ruby, there are far more
| attractive targets than Ruby if you care about
| performance
| wmoxam wrote:
| I found scrooge.
|
| Bah, humbug!
| dismalaf wrote:
| > Python is one of the Lingua Franca of scientific, data,
| and most importantly, ai communities
|
| You mean it's the most used frontend for all the C and
| C++ libraries that are used for scientific computing,
| data and AI.
| wiseowise wrote:
| Semantics.
| dismalaf wrote:
| Literally all those libraries are usable with Ruby.
| Libtorch, BLAS, LAPACK, Tensorflow, etc...
| wiseowise wrote:
| And with Java, and with Go, and with Rust, and with
| pretty much any language offering some form of FFI. But
| they're used with Python, and good luck convincing your
| interviewer that it should be used with Ruby.
| dismalaf wrote:
| > convincing your interviewer
|
| Some of us don't work for others and just program what we
| want.
| dismalaf wrote:
| Personally I don't care about speed for this category of
| language. I just bring it up because Python is one of the
| most used languages, is even slower, yet that's never
| held against it. Just seems like a lazy way to dismiss
| Ruby. Yeah, it's not as fast as C, Go, Rust or Java.
| Everyone knows and raw speed obviously isn't the point of
| a dynamic scripting language...
| wiseowise wrote:
| And has no ecosystem compared to Python.
|
| Speed isn't why people choose Python.
| mrinterweb wrote:
| There is [RBS](https://sorbet.org/) (part of ruby 3) and
| [sorbet](https://sorbet.org/). To be honest, these aren't
| widely used as far as I am aware. I don't know if it is runtime
| overhead, ergonomics, lack of type checking interest in the
| ruby community or something else. Type enforcement isn't a big
| part of ruby, and doesn't seem to be gaining much momentum.
| vicentereig wrote:
| I've been leaning hard into Sorbet runtime types for
| DSPy.rb[0] and finding real value. T::Struct at API
| boundaries, typed props for config, runtime validation where
| data enters the system.
|
| For generating (with LLMs) API clients and CLIs it's
| especially useful--define the shape once, get validation at
| ingress/egress for free.
|
| Maybe momentum is happening in new projects rather than
| retrofits? [0] https://oss.vicente.services/dspy.rb
| pmontra wrote:
| > lack of type checking interest in the ruby community
|
| IMHO if we wanted to write types in our programming language
| we would not have chosen Ruby for our programming tasks. We
| would have chosen one of the zillion of other languages.
| There were a lot of them when Ruby got traction about 20
| years ago and many other languages have been created after
| then. It's not surprising that one of the main proponent of
| typing in Ruby is Shopify, because their path away from Ruby
| is very costly.
|
| In my case one of the reasons I invested in Ruby is precisely
| because I did not have to write types.
|
| Does it make Ruby slower than Java, my main language in 2005?
| Yes.
|
| Is it fast enough for my customers? Yes. Most of them decided
| to use Ruby, then hired me.
|
| Do I have to write unit tests to check for types? I don't.
|
| Occasional problems that static types would have prevented to
| happen? Once or twice per year. Overall that's a good
| tradeoff because pleasing the type checker for non trivial
| types can be a time consuming task and some errors happen at
| runtime anyway, when the real world hits with its data a
| carefully type checked code base or a carelessly dynamic
| typed one. Think of an API suddenly returning a bad JSON,
| maybe an HTML 500 page. Static or dynamic typing, both won't
| help with that.
| jweir wrote:
| We have been adding Sorbet typing to our Rails application and
| it is a positive enhancement.
|
| It's not like Ruby becomes Haskell. But it does provide a good
| deal of additional saftey, less testing, LSP integration is
| good, and it is gradual.
|
| There is a performance hit but we found it to be quite small
| and not an issue.
|
| But there are area of our application that use Grape and it is
| too meta for Sorbet so we don't try and use it there.
| vicentereig wrote:
| Same here. T::Struct and T::Enums at API boundaries has been
| the sweet spot--typed request/response models, runtime
| validation at ingress/egress.
|
| I've been using this pattern for API clients[0] and CLIs[1]:
| define the shape once with Sorbet, get automatic JSON Schema
| generation when you need it.
|
| [0] https://github.com/vicentereig/exa-ruby [1]
| https://github.com/vicentereig/lf-cli
| lgas wrote:
| > It's not like Ruby becomes Haskell.
|
| Well, maybe next time.
| rsanheim wrote:
| _low_type_ is early days still, but I think this approach is
| clearly the future of ruby typing. If this gets baked into the
| language for full "compile" time support and minimal
| performance impact, it will be amazing: https://github.com/low-
| rb/low_type
| ksec wrote:
| It is definitely better than RBS and Sorbet. But unless
| Github / 37Signals or Shopify decide to use it, it is highly
| unlikely Ruby Core will consider it.
|
| Out of all three I think Shopify have the highest
| possibilities. There may be additional usefulness interms of
| ZJIT.
| Alifatisk wrote:
| Previously, RBS-inline was the closest answer to typed Ruby,
| it was the JSDoc of Ruby. Recently, when I stumbled upon
| low_type and tried it out in irb, it finally felt like "this
| is it, this is the TS of Ruby" and with runtime validation.
|
| I like it, it deserves attention, especially for those who
| are seeking for typed Ruby. With this, you can finally
| experience it, and the syntax feels more ergonomic than with
| Sorbet.
| fny wrote:
| This is so goergeous compared to the mess that's out there
| now.
| Gigachad wrote:
| There's projects trying to implement it. But I've never seen a
| project using typed Ruby.
|
| I think most people who cared just moved to typescript.
| dajonker wrote:
| In my honest opinion, if you can't live without static typing,
| Ruby just isn't for you.
|
| Adding static typing to a dynamic language mostly gives you the
| disadvantages of both, without a lot of benefits. It's better
| to stick to languages that were designed with static types from
| the start.
|
| I love programming in Ruby, having to worry about type
| annotations and the additional constraints that come with them
| would take a lot of the fun out of that.
| networked wrote:
| > Adding static typing to a dynamic language mostly gives you
| the disadvantages of both, without a lot of benefits.
|
| Can you elaborate? I don't share this experience, and I'm
| interested in bringing static typing to a language without
| static typing, so I'd like to understand. In new Python and
| JavaScript codebases, optional typing has had clear benefits
| for refactoring and correctness and low costs for me. Legacy
| codebases can be different.
| azuanrb wrote:
| Part of it is because Ruby imo, have a very nice syntax.
| With type annotation, it's becoming "ugly", a lot more
| verbose. It's no longer English-like. I do agree type have
| some advantages, but we need to get the DX right.
|
| I've been using Ruby for more than 10 years now, and I only
| started using LSP recently. To me it's a nice addition but
| I can live without it. Type is just one of the tools, not
| the only one imo. Not trying to sound negative but type is
| becoming more like a hammer analogy nowadays.
|
| And it's not limited to Ruby. Javascript, Python, all
| similar languages. Not everyone is a fan of type. We won't
| reach consensus imo and that's ok.
| clanky wrote:
| > _With type annotation, it 's becoming "ugly", a lot
| more verbose. It's no longer English-like._
|
| In our codebase that uses Sorbet I find this is really
| only true at function boundaries. Within a function it is
| pretty rare that anything needs to be spelled out with
| inline annotations to satisfy the compiler.
| codesnik wrote:
| This is my biggest irk about Sorbet: because its
| signatures are wordy and because it can't infer the
| generic type of a private method, it slightly pushes you
| towards NOT extracting helper methods if they are going
| to be 2-5 lines. With Sorbet annotation, it'd easily
| become 10 lines. So it pushes towards bigger methods, and
| those are not always readable.
|
| If only private methods would be allowed not having
| typing at all (with a promise of not being used in
| subclasses, for example), and Sorbet would be used mostly
| on the public surface of classes, it'd be much more
| tolerable for me.
| dajonker wrote:
| I don't have a great code example at hand unfortunately,
| but I found that people often tend to write more
| "nominally" typed code (expecting explicitly named classes)
| rather than taking advantage of duck typing (interfaces,
| structural types), meaning the code becomes more rigid,
| harder to change and more time wasted on resolving all the
| type checks, even if the code otherwise is perfectly
| reasonable and free of bugs.
|
| In other words, I found that the resulting code often
| looked more like Java but with weaker guarantees about
| types and much worse performance.
| vidarh wrote:
| I mostly agree with you, but I'd say adding typing to _low
| level core APIs_ is helpful in adding optimization
| opportunities.
| clanky wrote:
| > _Adding static typing to a dynamic language mostly gives
| you the disadvantages of both, without a lot of benefits._
|
| As an engineer at a firm doing heavy duty data pipelines and
| internal tooling in a Sorbet-ified codebase, I disagree
| pretty strongly. While Sorbet type signatures are never going
| to win a syntax beauty contest, they are more than worth
| their weight in the way I can rely on them to catch typing
| and nilability goofs, and often serve as helpful
| documentation. Meanwhile, the internal code of most functions
| I write still looks like straight Ruby, fluent and
| uncluttered.
|
| A good CI story that leans on tapioca was crucial here for
| us.
| ufmace wrote:
| I've come to think that adding halfway-typing to languages
| designed from the start to be dynamic is mostly not worth the
| bother. It may help a little bit sometimes, but there's always
| going to be holes. If you really want strong typing, it's
| better IMO to bite the bullet and move to a language designed
| for it. Let Ruby be Ruby, ditto Python, Javascript etc. Pick up
| some JVM, .NET, Rust, Go, etc if you really want strong types.
| weaksauce wrote:
| another early days project but pretty well thought out in that
| space: https://github.com/yippee-
| fun/empirical/blob/main/literally_...
| godd2 wrote:
| Ruby has always been typed.
| maz1b wrote:
| It's never Christmas without a new ruby version.
|
| The ruby::box thing looks pretty interesting, from a cursory
| glance you can run two simultaneous versions of something like a
| feature or rollout much more conveniently.
|
| Also being able to do if condition1 &&
| condition2 ... end
|
| on multiple lines rather than one - this is pretty nifty too!
| tebbers wrote:
| I've been doing if condition1 &&
| condition2 ... end
|
| for ages and it seems to work find, what am I missing with this
| new syntax?!
| mantas wrote:
| Personally && in the new line seems to be much better
| readability. Can't wait to use some smart cop to convert all
| existing multiline ifs in my codebase.
| Sammi wrote:
| Less likely to cause git merge conflict as you don't change
| the original line. You only add one.
| pmontra wrote:
| What we need is a syntax aware git diff
| https://news.ycombinator.com/item?id=42093756
| bbkane wrote:
| I agree, but I tend to find that "git diff aware syntax"
| also makes things simpler for humans as well
| fuzzythinker wrote:
| In languages where placement don't matter, like c/js, I
| prefer leading booleans. It makes it much easier to see the
| logic, especially with layers of booleans.
| AlecSchueler wrote:
| I prefer the new way because if you want to remove one
| condition you just delete the line rather than having to edit
| in multiple places.
| flopsamjetsam wrote:
| I first picked up this style from the GNU C++ style guide,
| and it's so handy I use it in every language that accepts
| it.
| zelphirkalt wrote:
| It's funny how I have been doing this way of writing the
| conditions in languages, where one can, like Python (if you
| use a pair of parentheses) and linters have yelled at me for
| ages to put the binary operator on the previous line. People
| herald these quite subjective things like truths, just
| because there is some tool, that they can delegate
| responsibility to.
| mathgeek wrote:
| For folks who scan code bases based on the front of lines, it
| makes it easier to grok. Also helps with deleting and
| inserting lines (similar to leading or trailing commas in
| lists).
| WJW wrote:
| I'm kinda hoping that eventually each ractor will run in it's
| own ruby::box and that each box will get garbage collected
| individually, so that you could have separate GCs per ractor,
| BEAM-style. That would allow them to truly run in parallel. One
| benefit should be to cut down p99 latency, since much fewer
| requests would be interrupted by garbage collection.
|
| I'm not actually in need of this feature at the moment, but it
| would be cool and I think it fits very well with the idea of
| ractors as being completely separated from each other. The
| downside is of course that sharing objects between ractors
| would get slower as you'd need to copy the objects instead of
| just sharing the pointer, but I bet that for most applications
| that would be negligible. We could even make it so that on
| ractor creation you have to pass in a box for it to live in,
| with the default being either a new box or the box of the
| parent ractor.
| byroot wrote:
| They already truly run in parallel in Ruby 4.0. The
| overwhelming majority of contention points have been removed
| in the last yet.
|
| Ruby::Box wouldn't help reducing contention further, they
| actually make it worse because with Ruby::Box classes and
| modules and an extra indirection to go though.
|
| The one remaining contention point is indeed garbage
| collection. There is a plan for Ractor local GC, but it
| wasn''t sufficiently ready for Ruby 4.0.
| WJW wrote:
| I know they run truly parallel when they're doing work, but
| GC still stops the world, right?
|
| Assuming you mean "because with Ruby::Box classes and
| modules _have_ an extra indirection to go though. " in the
| second paragraph, I don't understand why that would be
| necessary. Can't you just have completely separate boxes
| with their own copies of all classes etc, or does that use
| too much memory? (Maybe some COW scheme might work,
| doodling project for the holidays acquired haha)
|
| Anyway, very cool work and I hope it keeps improving!
| Thanks for 4.0 byroot!
| byroot wrote:
| > GC still stops the world, right?
|
| Yes, Ractor local GC is the one feature that didn't make
| it into 4.0.
|
| > Can't you just have completely separate boxes with
| their own copies of all classes etc, or does that use too
| much memory?
|
| Ruby::Box is kinda complicated, and still need a lot of
| work, so it's unclear how the final implementation will
| be. Right now there is no CoW or any type of sharing for
| most classes, except for core classes.
|
| Core classes are the same object (pointer) across all
| boxes, however they have a constant and method table for
| each box.
|
| But overall what I meant to say is that Box wouldn't make
| GC any easier for Ractors.
| RomanPushkin wrote:
| I'm happy to see v4.0, but 2025 was the year I switched from Ruby
| to Python after gradually drifting back to it more and more. The
| tipping point was when I had Claude Code automatically convert
| one of my Ruby projects to 100% Python - and after that, I just
| had no Ruby left.
|
| I spent over a decade enjoying Ruby and even wrote a book about
| it. At this point, though, Python has won for me: fastapi,
| pytorch, langchain, streamlit, and so on and on.
|
| It's a bit sad, but I'll always remember the Christmas gifts, and
| the syntax that is always so much better than Python.
| lcnmrn wrote:
| You should try Falcon too.
| 0xblinq wrote:
| Just by how much better the editor/IDE support is with Python
| it is a change worth to do.
|
| I just can't stand the excessive dynamism of Ruby. I understand
| some people prefer/enjoy it, it's just not for me.
| Bayko wrote:
| Langchain? I tried using/learning langchain then I found out
| that it was evolving so fast that even the latest ai models
| didn't have even remotely up to date information on it! Not to
| mention the hundreds of Google search results for ---- why do
| langchain docs suck? I finally switched to haystack and I have
| been really happy. (Don't work on corporate ai software this is
| just for personal use)
| nurettin wrote:
| Used Ruby for a decade, knew about it for more than that. I
| still sometimes use ruby syntax to communicate ideas with
| friends and colleagues.
|
| For me, the killer feature of Python was the typing module and
| the intellij pycharm community edition being free and RubyMine
| having a subscription fee.
| nix-zarathustra wrote:
| RubyMine is free for non-commercial usage.
| nurettin wrote:
| Ah, that must be a recent development.
| michaelcampbell wrote:
| It is; last couple months.
| jurgenkesker wrote:
| This year I also switched from Ruby to Kotlin on my hobby/light
| commercial backends. I just can't stand the way Ruby is not
| statically typed, and the resulting insecurity around if
| everything is actually doing what it should do. Kotlin gives me
| joy, and performance is actually better (trading memory
| requirements ofcourse, but that's not a big problem anymore). I
| still love Ruby, but only use it for simple scripts now.
| blandflakes wrote:
| This has sort of been my issue with Elixir. I've been doing
| Scala for years but I think Phoenix is really the best web
| story at the moment for how _I_ want to be building web apps.
| And while I believe that the benefits of static typing
| somewhat decrease in the web arena, it 's still frustrating
| to have to manage type relationships in my head.
|
| I'm hopeful that the incoming type system work makes me
| happier there, though I'd also prefer a nicer editor
| experience than is currently available.
| dmux wrote:
| > I believe that the benefits of static typing somewhat
| decrease in the web arena
|
| I've seen this sentiment expressed numerous times and have
| never found it to be true in my own work (e-comm), do you
| mind mentioning _what_ type of domain your web apps are in?
|
| Edit: or if not domain, what do you mean by "web arena"
| pansa2 wrote:
| > _fastapi, pytorch, langchain, streamlit, and so on and on_
|
| It's telling that your reasons for switching are all features
| of Python's ecosystem, not of the language itself. A lot of
| developers are moving to Python because of its libraries, and
| in many cases they don't care for the language at all.
|
| That's causing a problem for Python: many of these developers
| who'd rather be using different languages seem to want to morph
| Python _into_ their language of choice. The result is that the
| Python language is pulled in many different directions, and
| with each release gets increasingly bloated and strays further
| from its foundations.
|
| Ruby, on the other hand, has a community that's mostly made up
| of people who actually like the language. That allows it to do
| a much better job of staying true to its core philosophy.
| empthought wrote:
| None of what you say about Python is true. It's not even
| plausible. The Python language hasn't even had any
| significant syntax changes for four versions now; versions
| 3.11-3.14 are basically all internals optimizations.
|
| Why would you write something so clearly false?
| aobdev wrote:
| Have you worked on different types of Python projects? (Not
| in different codebases, different _types_ of codebases)
|
| I don't have any specific complaints about Python syntax
| because I can force it to get the job done...but
| homogeneous, it is not.
| chucke wrote:
| Both are true. Different camps meant that any significant
| change to the language was scrutinised loudly. If my memory
| doesn't fail me, the last significant changes from the time
| Guido was still in charge, and he mostly abandoned the BDFL
| because of backlash. Since then python has been on a
| constant "analysis paralysis" state, with only efforts
| about performance pushing through (no one complains about a
| faster horse).
| woodruffw wrote:
| > If my memory doesn't fail me, the last significant
| changes from the time Guido was still in charge, and he
| mostly abandoned the BDFL because of backlash
|
| I think Guido left the BDFL role in 2018, and we've
| gotten walrus operators, structured matching, and
| exception groups since then (just off the top of my
| head). There's also been significant language/grammar
| accommodations towards type annotations.
|
| Overall, I'm of the opinion that Python's language
| evolution has struck a pretty nice balance -- there's
| always going to be something new, but I don't feel like
| the syntax has stagnated.
| firemelt wrote:
| I get the sentiment, pandas, numpy, pytorch
|
| but I still love writing full stack webapp using rails so yeah
|
| thats why I really love pyCall
| Bolwin wrote:
| Have they improved tooling? I've yet to get any lsp working on
| windows
| ornornor wrote:
| IMO programming on windows is just asking for punishment.
| Unless it's a Microsoft language, you're so much better off on
| Linux or macOS.
| nchmy wrote:
| Or wsl2
| nurettin wrote:
| To be fair, vscode and .net core on linux is pretty much like
| having windows and visual studio at this point.
| array_key_first wrote:
| Without the debugger, unfortunately. You still need VS or
| Rider for that.
| seabrookmx wrote:
| The debugger works fine on Linux?
|
| The only thing missing are some profiling tools.
|
| If you really need those you're better off with Rider
| which is integrated with DotTrace.
| koshersalt wrote:
| That's cool if you can, but the majority of business
| desktops/laptops runs Windows. Hard to gain enterprise
| traction when it's hard to run tools on your local machine
| cwyers wrote:
| Just use WSL2 and Docker Desktop. VS Code has DevContainer
| support so you can standardize on a Docker image for your
| project.
| Alifatisk wrote:
| It's below expectations, and even worse on Windows.
|
| Luckily people seem to be aware of this and there was a whole
| talk about improving Ruby DX.
| epolanski wrote:
| Tried WSL2?
| digitaltrees wrote:
| Ruby is amazing. I recently built a layer on top of Rails that
| can generate an API from a single markdown file. I did the same
| thing in python but it was much harder and JavaScript would have
| been a beast. Ruby can meta program like nothing else.
| mierz00 wrote:
| Curious to hear more about this, do you have any examples?
| matltc wrote:
| Glad to see internal stack traces cleaned up (maybe we can get
| relative paths some day?) and Set finally get the respect it
| deserves!
| Alifatisk wrote:
| Relative path in stack trace would be so good!
| nomilk wrote:
| What's the relevance of ractors to the average web dev? Will
| ractors be useful directly in controllers/models/tasks? Or is it
| more that ractors will be useful to those working on the ruby
| language (and perhaps some gems - lower level stuff, perhaps),
| and therefore to the average ruby(/rails) programmer things 'just
| work', but faster?
| magmostafa wrote:
| Exciting to see Ruby 4.0.0 released! The new conditional syntax
| improvements (if condition1 && condition2) are really elegant.
| The Ruby::Box feature for true parallelism looks particularly
| promising for CPU-bound workloads. This could significantly
| improve performance in scenarios where we've historically had to
| resort to external services or other languages. Looking forward
| to seeing real-world benchmarks and adoption patterns emerge.
| pmdr wrote:
| 3.x has been awesome, let's hope 4 will be even better!
| magmostafa wrote:
| Ruby 4.0's parallel execution improvements are a game-changer for
| the ecosystem. The ruby::Box feature addresses one of the biggest
| pain points - GIL limitations - while maintaining Ruby's
| elegance.
|
| What's particularly exciting is how this positions Ruby for
| modern workloads. With proper parallelism, Ruby apps can finally
| compete with Go and Node.js in concurrent scenarios without
| sacrificing developer happiness.
|
| The typing improvements also can't be understated. Gradual typing
| strikes the right balance - it helps teams scale codebases
| without forcing the verbosity of Java or the complexity of
| TypeScript's type gymnastics.
|
| Looking forward to seeing how the Rails ecosystem adopts these
| features. This could spark a Ruby renaissance in 2025.
| jadbox wrote:
| > "With proper parallelism, Ruby apps can finally compete with
| Go and Node.js in concurrent scenarios without sacrificing
| developer happiness"
|
| In theory, maybie. Parallelism support isn't a boolean though
| as there's a lot of additional factors at play. Just as one
| example, late stage Visual Basic also got parallelism support,
| but it really didn't help the overall positioning of the the
| language among its peers.
| codesnik wrote:
| from what I understand, ruby::Box has nothing to do with GIL.
| At least, not yet.
| chucke wrote:
| Happy bday ruby!
|
| For the usual doomsdaysayers saying "ruby can't X so I left it
| for Y", when X is typing, RBS is becoming the accepted standard
| (now that sorbet supports it),and RBS inline notation next to
| signature/code too (for peeps complaining about separate files);
| when X is LSP, ruby-lsp is the standard and already supports "go
| to definition" (its major hole for a long time), and its plugin
| architecture allows other other features to reuse the same code
| AST/index (So that each linter/formatter/type checker doesn't
| have to parse their own); when X is parallelism, ractors are have
| actually become performant in a lot of common cases, and it's
| only missing some GC improvements to be truly non-experimental.
|
| There are new shiny things like ZJIT or Box, but even the core
| team recommends against using them in production for now. But
| they'll get better, as its been happening with the things listed
| above.
|
| No wildly new syntax changes is also a good thing. Should help
| alternative implementations catch up.
| screenothethird wrote:
| It's just inferior to Python, nobody is making a more complex
| argument than that. Why ever use Ruby when there's a virtually
| identical system that's faster with a bigger community.
| amazingman wrote:
| Blanket statements like this are unhelpfully tribal. Ruby has
| its uses, and underpins one of the most successful (and
| cloned) MVC frameworks of all time. But yeah, Python received
| the attention of data scientists early on and now it's a
| lingua franca of sorts in that domain. Since AI is so hot
| right now that makes Python seem superior, but really that's
| just contingency.
|
| If you're going to make claims, support them.
| block_dagger wrote:
| Why? Because Python is generally slower, uses significant
| whitespace in its syntax, and lacks the metaprogramming
| features of Ruby.
| meesles wrote:
| In what ways is it inferior? Neither Ruby or Python are
| 'fast', so if that is one of your qualifiers you've already
| made a suboptimal choice.
|
| As for a bigger community, what does that serve? The large
| python community adds misdirection and more voices to a
| language that lacks some basic features still. Async/sync
| code models are still being finalized whereas Ruby has been
| stable in this regard for 10+ years. Same with tooling - the
| Ruby side is more consistent and stable: Sidekiq for
| background jobs (Celery is barely coming to maturity),
| Bundler for dependencies (pip? poetry? uv?). Mature auth +
| other frameworks like Devise.
|
| Having worked in both languages professionally, I strongly
| disagree with your take.
| Calavar wrote:
| Because Ruby is just a better thought out language than
| Python is. It had a sane package management story 15 years
| before Python. It doesn't rely on weird hacks like exception
| throwing for iterator control flow. It doesn't have nearly as
| many warts and footguns on basic operations (for example, in
| Python csv.writer(file).writerows(rows) is broken unless you
| remembered to set the newline mode on the file; in Ruby
| file.write(rows.to_csv) just works). Thanks to a sane VM
| design it's mainline JIT can actually run code faster than
| interpreted code (something that CPython's JIT can't do [1])
|
| Many Pythonistas are woefully ignorant of what's going on
| outside their siloed community.
|
| [1] https://fidget-spinner.github.io/posts/jit-
| reflections.html
| lern_too_spel wrote:
| Everything being mutable by default, including strings, is
| about as big a foot gun as you can find in a high level
| language.
| bjoli wrote:
| Ruby is a lot less awful than Python in my opinion. That is
| of course a very subjective opinion. The only reason I write
| more Python than Ruby is that ruby lacks the libraries I
| need.
|
| Somewhere along the line Python got all the momentum, and
| ruby got none and now python is better if you just want to
| get shit done.
|
| But man. I wish it was the other way around. I have one code
| snippet that summarises what I dislike about python:
| if input() == "dynamic scope?": defined =
| "happyhappy" print(defined)
|
| Seeing that I understand why I see yuck in just about every
| corner of python.
|
| Edit: in ruby it also works, but the variable is at least
| always defined.
| qezz wrote:
| > in ruby it also works, but the variable is at least
| always defined.
|
| How is this even a pro? I agree that Python scoping rules
| are frustrating, but tbh not sure if I would prefer Ruby's
| behavior in this case
| bjoli wrote:
| Well. If python is a dynamically scoped language, what
| they do is correct. If they are lexically scoped (which
| python is described as) the variable defined in the if
| should never have different visibility in the same scope.
|
| In a lexically scoped language you don't define variables
| conditionally. What ruby does is also icky, but obviously
| the developers of both python and ruby wanted to save the
| developer an extra declaration. The ruby version is at
| least more correct from a lexical standpoint (it is set
| to nil if left "nondefined").
| BurningFrog wrote:
| A lot of times 2-3 lines of Ruby needs 5-8 lines in Python.
| voidfunc wrote:
| Python is great and I love writing glue in it, but Ruby is
| just a better designed language and ecosystem overall.
| pansa2 wrote:
| > _that's faster_
|
| In every test I've done, Ruby has been faster than Python. In
| my experience that's been the case since Ruby 1.9, with the
| move to YARV.
| osigurdson wrote:
| I don't think anyone says: "I switched from Python to Ruby"
| (of vice versa) for performance.
| pansa2 wrote:
| True. Choosing between the two languages usually comes
| down to their library ecosystems - or more bluntly, to
| Rails on one hand vs NumPy on the other.
|
| Nonetheless, it's still common for people to talk about
| the relative performance of the two languages, and to
| claim that Ruby is slower than Python. As someone who's
| actually tested this, it hasn't been true for 15 years.
| rco8786 wrote:
| Fairly hardcore rubyist here. Ruby-lsp is excellent. But in no
| way is RBS becoming standard. Maybe it will, I don't know. But
| adoption is very, very low as of today. Rbs-inline is just
| someone's pet project and has very little activity (though it
| does appear that the person who wrote it is trying to implement
| it directly into Rbs now, which would be great)
|
| Personally I can't see any comment based typing system gaining
| real traction.
| block_dagger wrote:
| As long as Matz is firmly against, inline typing should never
| be a part of Ruby. I started working on a large Rails
| codebase that adopted Sorbet and it is nothing but an
| impediment to progress.
| throwaway613745 wrote:
| DHH also doesn't like typing in Ruby at all, and Rails is
| designed around what he likes.
| rco8786 wrote:
| I think it will need to be a strong 3rd party that
| basically gives it the Typescript treatment.
|
| Adds type annotations to the core language syntax. The
| compiler does type checking, strips the annotations, and
| outputs plain Ruby.
| anamexis wrote:
| Sorbet is backed by Stripe.
|
| Why is it important to be a separate layer that compiles
| to plain untyped Ruby?
| __float wrote:
| I work in a large Sorbet codebase (though it isn't a Rails
| one) and it's a huge boon IMO. The number of tests we _don
| 't_ need to write because of Sorbet is really nice.
|
| It does occasionally require structuring your code
| differently, but I find the type-system-encouraged approach
| often gives a more elegant and harder-to-misuse interface
| in the end.
| prh8 wrote:
| You work in a large Ruby codebase that _isn't_ Rails?!
| Are you hiring??
| ezekg wrote:
| I was assuming Stripe, but would love to hear of others!
| zingar wrote:
| Very curious to hear about the specific cases where types
| make tests unnecessary.
|
| I spend my working life swapping between Ruby and
| typescript projects and the typescript project is utter
| garbage with poor test coverage that needs a day of human
| QA for every build whereas the Ruby project is well
| tested such that we know that CI passing means it's good
| to be released.
| danmaz74 wrote:
| > adopted Sorbet and it is nothing but an impediment to
| progress
|
| How so?
|
| I never really missed types in Ruby, even if I like them a
| lot in typescript, but right now I'm doing some "vibe
| coding" on a personal project and I was thinking about
| trying Sorbet. I think that it could help Claude Code avoid
| some mistakes it often makes which make it waste a lot of
| time fixing.
| zingar wrote:
| Interesting: how is CC in your experience at writing
| tests and then using them to avoid mistakes?
| danmaz74 wrote:
| When writing non-vibe-coded software I use CC a lot to
| write tests, but I have a skill to tell it not to create
| redundant tests, which otherwise it tends to do, and I
| have to check them anyway to ensure that they cover what
| needs to be covered, and sometimes to trim them down.
|
| When vibe coding, what I noticed is that CC tends to make
| mistakes which it does catch with tests and fix on its
| own, but my hope is that using Sorbet this will happen
| much less, and thus development will go faster with less
| (slow) test cycles.
| chucke wrote:
| Maybe I wasn't clear, but until now there were 2 types of
| type notations being debated, RBS and sorbet/RBI. Sorbet
| adopting RBS means that's the lowest common denominator.
| Typing is definitely not a standard, not yet. rbs-inline is
| definitely not a pet project, it's the RBS creator response
| to the main complaint about RbS , its the reason sorbet
| finally adopted it, and will be part of mainline rbs gem.
| zhisme wrote:
| Am I the only one who expected something bigger in a major
| release? With Ruby 3 we had the whole "3x3" story and significant
| performance improvements. This release feels more like a minor
| version, something closer to 3.5.
|
| I don't want to downplay the work done by the maintainers on the
| contrary, huge thanks to them. But I do feel the version number
| is a bit misleading.
|
| That said, the work on the ZJIT[1] compiler is massive. It's
| serious, professional engineering, and definitely deserves
| respect.
|
| [1]: https://rubykaigi.org/2025/presentations/maximecb.html
| codesnik wrote:
| eh, it's just a little celebration. Let Matz have it.
| prh8 wrote:
| One issue is gems which are locked `ruby < 4.0` which will
| now require updating, and releasing 4.0 instead of 3.5 was
| only done very recently.
|
| For a more concrete example, the grpc gem locks Ruby versions
| (< 3.5), and they refuse to change it. So until they support
| the next Ruby version, we could test ruby-next by testing
| with a preview release. This worked for 3.4 and 3.5, but now
| doesn't work with 4.0 (bundler resolves 4.0-preview2 > 3.5,
| whereas we are able to do 3.5-preview1).
|
| So unless I feel like doing a lot of grunt work (which I
| don't), I can't even test Ruby 4 in our app until they
| release a new version. And while I recognize this is an issue
| with the gem, it is a consequence of choosing to do 4.0.
| Doctor_Fegg wrote:
| Ruby doesn't follow semver.
| werdnapk wrote:
| I think the major version change is more of a celebratory thing
| with Ruby being 30 years as of 2025.
| Exuma wrote:
| I love ruby so much
| __float wrote:
| If I remember correctly, the namespaces feature (now released as
| Ruby::Box) had some pretty severe performance penalties (possibly
| even for code that doesn't use it?).
|
| Does anyone know if that's been improved?
| auraham wrote:
| I gave it a try a few months ago. The first thing that I searched
| for was the REPL. Comparing it with Python, I prefer ipython over
| irb. It would be nice to see some improvement on DX on the REPL
| side
| Lio wrote:
| What actionable things do you think IRB is missing vs ipython?
| schneems wrote:
| Now available on Heroku https://devcenter.heroku.com/changelog-
| items/3521
| bvan wrote:
| For someone wanting to learn Ruby in 2025/26, what are some good
| up-to-date references, outside of the official documentation? Are
| there any recently-published books which stand-out?
| dueyfinster wrote:
| I've done the pragmatic studio elixir and erlang courses and
| they are high quality. They do the same for Ruby and Rails[1]
|
| [1]: https://pragmaticstudio.com/rails
| msie wrote:
| I would like multi-line comments to make it into Ruby one day.
| riffraff wrote:
| But they have always been there? =begin/=end, perldoc style.
___________________________________________________________________
(page generated 2025-12-25 23:01 UTC)