{"id":1757,"date":"2026-11-02T11:18:49","date_gmt":"2026-11-02T11:18:49","guid":{"rendered":"https:\/\/ruby-doc.org\/learn\/?p=1757"},"modified":"2026-11-02T11:18:50","modified_gmt":"2026-11-02T11:18:50","slug":"ruby-4-0-new-features","status":"publish","type":"post","link":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/","title":{"rendered":"Ruby 4.0 New Features: What Changed and What to Try"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Ruby 4.0 new features at a glance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby 4.0 new features include reverse array search, character selectors for string trimming, a core Set class, experimental Ruby Box isolation and the experimental ZJIT compiler. Ractor also gains a Port API for messages. You can try some changes in a short script; the runtime facilities need testing in your application&#8217;s environment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use a maintained Ruby 4.0 patch release for your own trial. The collection examples here passed checks in Ruby 4.0.0 using the official WebAssembly build. Those checks reproduce the small examples. They do not measure a native application&#8217;s performance.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"1250\" src=\"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp\" alt=\"Ruby 4.0 new features map covering array and string helpers, core Set, experimental Ruby Box and ZJIT, and Ractor ports\" class=\"wp-image-1756\" srcset=\"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp 1600w, https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map-300x234.webp 300w, https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map-1024x800.webp 1024w, https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map-768x600.webp 768w, https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map-1536x1200.webp 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><figcaption class=\"wp-element-caption\">Ruby 4.0 new features range from everyday collection helpers to experimental runtime facilities.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Feature<\/th><th>What changed<\/th><th>A useful first question<\/th><\/tr><\/thead><tbody><tr><td>Array#rfind<\/td><td>Search an array from its end for a matching element.<\/td><td>Does the last matching record have meaning in this ordering?<\/td><\/tr><tr><td>String#strip selectors<\/td><td>Choose characters to remove from the ends.<\/td><td>Am I trimming characters or removing a whole token?<\/td><\/tr><tr><td>Set in core<\/td><td>Set becomes a core class.<\/td><td>Do I need uniqueness, ordering or both?<\/td><\/tr><tr><td>Ruby Box<\/td><td>Experimental separation of definitions within a process.<\/td><td>Which definitions or patches need separation?<\/td><\/tr><tr><td>ZJIT<\/td><td>A new experimental JIT compiler.<\/td><td>What does the actual workload measure?<\/td><\/tr><tr><td>Ractor::Port<\/td><td>Explicit ports for messages between Ractors.<\/td><td>Who receives, and who closes the channel?<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Try the collection changes first<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Arrays maintain a particular order. Sometimes you need the last item that meets a condition. Ruby 4.0 adds Array#rfind for that search. It starts from the right and returns the first qualifying element it encounters.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>values = &#91;5, 2, 8, 4]\nvalues.rfind { |value| value &gt; 5 }\n# =&gt; 8<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You receive one matching item, rather than a list of every match. If no item qualifies, the result is nil. The original array keeps its order, which matters when other code continues to use the same collection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Decide what the order means before choosing the search. The final entry in an array does not inherently represent the newest record or the highest value. Searching backwards through records imported in a random order does not make those records a historical sequence.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For a project that also supports Ruby 3.4, compare this with reverse_each.find. Wait until your supported runtimes include rfind before adopting it. Keep the expected answer explicit in a test so a shorter spelling does not inadvertently change the business rule.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Trim selected characters, not an exact wrapper<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">String#strip normally removes leading and trailing whitespace. Ruby 4.0 also lets it accept character selectors. This example selects angle brackets for trimming while leaving the letters between them intact.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>label = \"&lt;&lt;Ruby&gt;&gt;\"\nlabel.strip(\"&lt;&gt;\")\n# =&gt; \"Ruby\"\nlabel\n# =&gt; \"&lt;&lt;Ruby&gt;&gt;\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The non-bang method creates a new string without changing the original label. A selector describes characters, rather than an exact token such as an opening tag. If you need to remove one known prefix, define that requirement separately from trimming selected characters at either end.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Try another input with an angle bracket in the middle. Trimming only affects the boundaries, so the interior bracket remains. That extra check tells you more than testing only the tidy input that first motivated the code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Selectors also support character ranges and other selection forms. Consult the current method documentation before using a complicated pattern. For ordinary whitespace trimming, the argument-free call remains clear.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set joins the core classes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Set becomes a core class rather than an autoloaded standard-library class. It still models a collection in which duplicate members do not belong. In this example, two occurrences of the same integer contribute one member.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>numbers = Set&#91;2, 2, 5]\nnumbers.size\n# =&gt; 2\nnumbers.include?(5)\n# =&gt; true<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Choose the data structure for the data. An array can be a better fit when positions or repeated values matter. A set expresses uniqueness and does not supply a missing sorting rule for your application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby 4.0 also changes Set&#8217;s inspection display. A test that compares a printed representation might be checking an actual interface requirement, or it might merely depend on a convenient debugging string. Where possible, assert membership and size directly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ruby Box separates definitions within a process<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby Box provides experimental spaces for definitions such as classes, modules, libraries and monkey patches. The official <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2025\/12\/25\/ruby-4-0-0-released\/\">Ruby 4.0 release announcement<\/a> introduces it alongside ZJIT and the other major changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine a test that modifies a method and accidentally affects a later test. This is a problem of definition separation. The useful question becomes which version of a definition a piece of code should see, rather than merely which version of some data it should read.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enable Ruby Box when starting the process. Treat it as an experiment with your dependency set, especially when native extensions and frameworks are involved. The documentation lists known issues; a successful isolated example does not establish compatibility with a whole application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A Box is not an operating-system security boundary. Putting untrusted code in one does not make that code safe to execute. Evaluate it for definition isolation and keep track of what still shares the process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ZJIT and Ractor need workload-specific evaluation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">ZJIT is an experimental just-in-time compiler introduced in Ruby 4.0. Adding a compiler does not necessarily make every program faster. The 4.0.0 announcement described ZJIT as faster than the interpreter but not yet as fast as YJIT, and advised experimentation rather than immediate production deployment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keep the comparison tied to that release. Later patches and future Ruby branches can change it. Test a representative workload with a documented runtime build and configuration before making a performance claim about your application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ractor changes message handling too. Ractor::Port represents a channel between Ractors. The Ractor that created a port can receive messages through it and close it. Older message-passing examples may need updating before they work in a 4.0 project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A single successful run does not cover concurrency behaviour. Check empty queues, closed channels, worker failures and shutdown. This guide&#8217;s examples do not execute Ractor concurrency or benchmark JIT compilers; the runtime checks cover the pure collection operations shown above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Predict the results of the Ruby 4.0 new features<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before opening the answer, change one input in each collection example. Replace the reverse-search condition with a value above ten. Put an angle bracket inside a label, then count unique integers in a list containing duplicates.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>What should those three checks show?<\/summary>\n<p class=\"wp-block-paragraph\">The search returns nil when nothing matches. Trimming selected brackets leaves an interior bracket in place. A Set keeps one member for each distinct integer. These are separate rules: search direction, string boundaries and uniqueness. The accompanying code checks verify them independently.<\/p>\n<\/details>\n\n\n\n<p class=\"wp-block-paragraph\">If the syntax is unfamiliar, our <a href=\"https:\/\/ruby-doc.org\/learn\/ruby-programming-language-overview\/\">Ruby programming language overview<\/a> explains how values, arrays, blocks and return values work together. Understanding the returned object helps more than memorising a new method name.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Check compatibility before adopting the new helpers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Ruby 4.0 NEWS lists user-visible updates, including removals and library packaging changes. Use it to identify changes that affect your project. A feature overview still needs an API review against the code you actually run.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First make the existing application work under the chosen runtime. Once it works, add a helper where it makes the code easier to read. Keep experimental runtime work in separate commits so a failure has fewer possible causes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Which Ruby versions must a shared library support?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Your development machine may use Ruby 4.0 while some people using the library still run 3.4. Adding a new method call adds a requirement for those users. Test both the oldest supported runtime and the newer one, and make the declared Ruby requirement match the library&#8217;s code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Passing tests on your own machine does not establish continued support for older Ruby versions. Keep that support check visible in CI. It is easier to find an unsupported method there than after somebody installs a released gem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You do not need to turn on every optional facility to use a collection helper. Ruby Box needs a startup setting; <a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/master\/doc\/jit\/zjit.md\">ZJIT depends on<\/a> the runtime build and configuration. Record which optional features a test actually enables. Otherwise, two developers may compare results from different configurations while believing they ran the same test.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby 4.0 new features solve different kinds of problems. A collection helper can clarify a short expression. Definition separation, a compiler and concurrency facilities need a more deliberate trial. Choose a change whose purpose and expected result you can explain.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A practical tour of Ruby 4.0&#8217;s collection helpers, core classes and experimental runtime features, with small tested examples and checks for existing projects.<\/p>\n","protected":false},"author":3,"featured_media":1756,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1757","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruby-tips"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":7}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ruby 4.0 New Features: What Changed and What to Try<\/title>\n<meta name=\"description\" content=\"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ruby 4.0 New Features: What Changed and What to Try\" \/>\n<meta property=\"og:description\" content=\"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/\" \/>\n<meta property=\"og:site_name\" content=\"Ruby-Doc Learn\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-02T11:18:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-02T11:18:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"1250\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"James Britt\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"James Britt\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/\"},\"author\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/james-britt\\\/#james-britt\"},\"headline\":\"Ruby 4.0 New Features: What Changed and What to Try\",\"datePublished\":\"2026-11-02T11:18:49+00:00\",\"dateModified\":\"2026-11-02T11:18:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/\"},\"wordCount\":1352,\"publisher\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/ruby-4-0-new-features-map.webp\",\"articleSection\":[\"Ruby tips\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/\",\"name\":\"Ruby 4.0 New Features: What Changed and What to Try\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/ruby-4-0-new-features-map.webp\",\"datePublished\":\"2026-11-02T11:18:49+00:00\",\"dateModified\":\"2026-11-02T11:18:50+00:00\",\"description\":\"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#primaryimage\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/ruby-4-0-new-features-map.webp\",\"contentUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/ruby-4-0-new-features-map.webp\",\"width\":1600,\"height\":1250,\"caption\":\"Ruby 4.0 new features range from everyday collection helpers to experimental runtime facilities.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/ruby-4-0-new-features\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruby 4.0 New Features: What Changed and What to Try\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#website\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\",\"name\":\"Ruby-Doc Learn\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\",\"name\":\"Ruby-Doc Learn\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-doc-logo-transparent.png\",\"contentUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-doc-logo-transparent.png\",\"width\":1650,\"height\":305,\"caption\":\"Ruby-Doc Learn\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/james-britt\\\/#james-britt\",\"name\":\"James Britt\",\"image\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/jgb_self-portrait-20140914.png\",\"description\":\"Creator and long-term maintainer of Ruby-Doc.org, founder of Neurogami, and author of practical Ruby tutorials for Ruby-Doc Learn.\",\"sameAs\":[\"https:\\\/\\\/jamesbritt.com\\\/\",\"https:\\\/\\\/neurogami.com\\\/\",\"https:\\\/\\\/www.oreilly.com\\\/pub\\\/au\\\/2595\",\"https:\\\/\\\/www.rubyevents.org\\\/profiles\\\/james-britt\"],\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/james-britt\\\/\",\"jobTitle\":\"Ruby developer and writer\",\"knowsAbout\":[\"Ruby programming language\",\"Ruby documentation\",\"JRuby\",\"Open Sound Control\",\"Software development\"],\"affiliation\":{\"@type\":\"Organization\",\"name\":\"Ruby-Doc.org\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ruby 4.0 New Features: What Changed and What to Try","description":"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/","og_locale":"en_US","og_type":"article","og_title":"Ruby 4.0 New Features: What Changed and What to Try","og_description":"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.","og_url":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/","og_site_name":"Ruby-Doc Learn","article_published_time":"2026-11-02T11:18:49+00:00","article_modified_time":"2026-11-02T11:18:50+00:00","og_image":[{"width":1600,"height":1250,"url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp","type":"image\/webp"}],"author":"James Britt","twitter_card":"summary_large_image","twitter_misc":{"Written by":"James Britt","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#article","isPartOf":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/"},"author":{"@id":"https:\/\/ruby-doc.org\/learn\/james-britt\/#james-britt"},"headline":"Ruby 4.0 New Features: What Changed and What to Try","datePublished":"2026-11-02T11:18:49+00:00","dateModified":"2026-11-02T11:18:50+00:00","mainEntityOfPage":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/"},"wordCount":1352,"publisher":{"@id":"https:\/\/ruby-doc.org\/learn\/#organization"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#primaryimage"},"thumbnailUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp","articleSection":["Ruby tips"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/","url":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/","name":"Ruby 4.0 New Features: What Changed and What to Try","isPartOf":{"@id":"https:\/\/ruby-doc.org\/learn\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#primaryimage"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#primaryimage"},"thumbnailUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp","datePublished":"2026-11-02T11:18:49+00:00","dateModified":"2026-11-02T11:18:50+00:00","description":"Explore Ruby 4.0 new features, from reverse array search and string selectors to Ruby Box, ZJIT and Ractor ports, with tested examples and clear limits.","breadcrumb":{"@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#primaryimage","url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp","contentUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/11\/ruby-4-0-new-features-map.webp","width":1600,"height":1250,"caption":"Ruby 4.0 new features range from everyday collection helpers to experimental runtime facilities."},{"@type":"BreadcrumbList","@id":"https:\/\/ruby-doc.org\/learn\/ruby-4-0-new-features\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ruby-doc.org\/learn\/"},{"@type":"ListItem","position":2,"name":"Ruby 4.0 New Features: What Changed and What to Try"}]},{"@type":"WebSite","@id":"https:\/\/ruby-doc.org\/learn\/#website","url":"https:\/\/ruby-doc.org\/learn\/","name":"Ruby-Doc Learn","description":"","publisher":{"@id":"https:\/\/ruby-doc.org\/learn\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ruby-doc.org\/learn\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ruby-doc.org\/learn\/#organization","name":"Ruby-Doc Learn","url":"https:\/\/ruby-doc.org\/learn\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/logo\/image\/","url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-doc-logo-transparent.png","contentUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-doc-logo-transparent.png","width":1650,"height":305,"caption":"Ruby-Doc Learn"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/ruby-doc.org\/learn\/james-britt\/#james-britt","name":"James Britt","image":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/jgb_self-portrait-20140914.png","description":"Creator and long-term maintainer of Ruby-Doc.org, founder of Neurogami, and author of practical Ruby tutorials for Ruby-Doc Learn.","sameAs":["https:\/\/jamesbritt.com\/","https:\/\/neurogami.com\/","https:\/\/www.oreilly.com\/pub\/au\/2595","https:\/\/www.rubyevents.org\/profiles\/james-britt"],"url":"https:\/\/ruby-doc.org\/learn\/james-britt\/","jobTitle":"Ruby developer and writer","knowsAbout":["Ruby programming language","Ruby documentation","JRuby","Open Sound Control","Software development"],"affiliation":{"@type":"Organization","name":"Ruby-Doc.org","url":"https:\/\/ruby-doc.org\/"}}]}},"_links":{"self":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1757","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/comments?post=1757"}],"version-history":[{"count":2,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1757\/revisions"}],"predecessor-version":[{"id":1759,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1757\/revisions\/1759"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/media\/1756"}],"wp:attachment":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/media?parent=1757"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/categories?post=1757"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/tags?post=1757"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}