Вийшов Ruby 4.0.0

Опублікував naruse 25-12-2025
Переклав: Andrii Furmanets

Ми раді повідомити про випуск Ruby 4.0.0. Ruby 4.0 представляє “Ruby Box” та “ZJIT”, а також додає багато покращень.

Ruby Box

Ruby Box — це нова (експериментальна) функція для забезпечення розділення визначень. Ruby Box вмикається, коли встановлена змінна середовища RUBY_BOX=1. Клас — Ruby::Box.

Визначення, завантажені в box (коробку), ізольовані в ній. Ruby Box може ізолювати/розділяти monkey patches, зміни глобальних/класових змінних, визначення класів/модулів та завантажені нативні/ruby бібліотеки від інших boxes.

Очікувані варіанти використання:

  • Запуск тестових випадків у box для захисту інших тестів, коли тестовий випадок використовує monkey patches для перевизначення чогось
  • Запуск boxes веб-додатків паралельно для виконання blue-green розгортання на сервері додатків у процесі Ruby
  • Запуск boxes веб-додатків паралельно для оцінки оновлень залежностей протягом певного періоду часу шляхом перевірки відмінностей у відповідях за допомогою коду Ruby
  • Використовується як базовий (низькорівневий) API для реалізації свого роду API “пакунків” (високорівневого) (він ще не спроектований)

Для детальнішої інформації про “Ruby Box”, дивіться Ruby::Box. [Feature #21311] [Misc #21385]

ZJIT

ZJIT — це новий just-in-time (JIT) компілятор, який розробляється як наступне покоління YJIT. Вам потрібен Rust 1.85.0 або новіший, щоб зібрати Ruby з підтримкою ZJIT, і ZJIT вмикається, якщо вказано --zjit.

Ми створюємо новий компілятор для Ruby, тому що хочемо одночасно підняти стелю продуктивності (більший розмір одиниці компіляції та SSA IR) та заохотити більше внесків ззовні (стаючи більш традиційним компілятором методів). Дивіться наш блог для деталей.

ZJIT швидший за інтерпретатор, але ще не такий швидкий, як YJIT. Ми заохочуємо вас експериментувати з ZJIT, але, можливо, утримайтеся від розгортання його у виробництві на даний момент. Слідкуйте за Ruby 4.1 ZJIT.

Покращення Ractor

Ractor, механізм паралельного виконання Ruby, отримав кілька покращень. Новий клас, Ractor::Port, був представлений для вирішення проблем, пов’язаних з надсиланням та отриманням повідомлень (дивіться наш блог). Крім того, Ractor.shareable_proc полегшує спільне використання об’єктів Proc між Ractors.

З боку продуктивності, багато внутрішніх структур даних було покращено для значного зменшення конкуренції за глобальне блокування, відкриваючи кращий паралелізм. Ractors тепер також поділяють менше внутрішніх даних, що призводить до меншої конкуренції кешу CPU при паралельному запуску.

Ractor був вперше представлений у Ruby 3.0 як експериментальна функція. Ми прагнемо зняти статус “експериментальний” наступного року.

Зміни мови

  • *nil більше не викликає nil.to_a, подібно до того, як **nil не викликає nil.to_hash. [Feature #21047]

  • Логічні бінарні оператори (||, &&, and та or) на початку рядка продовжують попередній рядок, як fluent dot. Наступні приклади коду є еквівалентними:

      if condition1
         && condition2
        ...
      end
    

    Раніше:

      if condition1 && condition2
        ...
      end
    
      if condition1 &&
         condition2
        ...
      end
    

    [Feature #20925]

Оновлення основних класів

Примітка: Ми перераховуємо лише видатні оновлення класів.

  • Array

    • Array#rfind додано як більш ефективну альтернативу array.reverse_each.find [Feature #21678]
    • Array#find додано як більш ефективне перевизначення Enumerable#find [Feature #21678]
  • Binding

    • Binding#local_variables більше не включає нумеровані параметри. Також, Binding#local_variable_get, Binding#local_variable_set та Binding#local_variable_defined? відхиляють обробку нумерованих параметрів. [Bug #21049]

    • Binding#implicit_parameters, Binding#implicit_parameter_get та Binding#implicit_parameter_defined? додано для доступу до нумерованих параметрів та параметра “it”. [Bug #21049]

  • Enumerator

    • Enumerator.produce тепер приймає необов’язковий іменований аргумент size для вказівки розміру перечислювача. Це може бути ціле число, Float::INFINITY, об’єкт, що викликається (наприклад, лямбда), або nil, щоб вказати невідомий розмір. Якщо не вказано, розмір за замовчуванням Float::INFINITY.

        # Нескінченний перечислювач
        enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
        enum.size  # => Float::INFINITY
      
        # Скінченний перечислювач з відомим/обчислюваним розміром
        abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
        traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
          raise StopIteration if it == "/"
          File.dirname(it)
        }
        traverser.size  # => 4
      

      [Feature #21701]

  • ErrorHighlight

    • Коли викликається ArgumentError, тепер відображаються фрагменти коду для обидвох: виклику методу (caller) та визначення методу (callee). [Feature #21543]

      test.rb:1:in 'Object#add': wrong number of arguments (given 1, expected 2) (ArgumentError)
      
          caller: test.rb:3
          | add(1)
            ^^^
          callee: test.rb:1
          | def add(x, y) = x + y
                ^^^
              from test.rb:3:in '<main>'
      
  • Fiber

    • Впроваджено підтримку аргументу Fiber#raise(cause:), подібного до Kernel#raise. [Feature #21360]
  • Fiber::Scheduler

    • Впроваджено Fiber::Scheduler#fiber_interrupt для переривання файбера з заданим виключенням. Початковий варіант використання — перервати файбер, який чекає на блокуючу операцію введення-виведення, коли операція введення-виведення закрита. [Feature #21166]

    • Впроваджено Fiber::Scheduler#yield, щоб дозволити планувальнику файберів продовжувати обробку, коли сигнальні виключення вимкнені. [Bug #21633]

    • Повторно впроваджено хук Fiber::Scheduler#io_close для асинхронного IO#close.

    • Виклик Fiber::Scheduler#io_write при скиданні буфера запису IO. [Bug #21789]

  • File

    • File::Stat#birthtime тепер доступний на Linux через системний виклик statx, коли це підтримується ядром та файловою системою. [Feature #21205]
  • IO

    • IO.select приймає Float::INFINITY як аргумент тайм-ауту. [Feature #20610]

    • Застаріла поведінка, створення процесу методами класу IO з провідним |, була видалена. [Feature #19630]

  • Kernel

    • Kernel#inspect тепер перевіряє наявність методу #instance_variables_to_inspect, дозволяючи контроль над тим, які змінні екземпляра відображаються в рядку #inspect:

        class DatabaseConfig
          def initialize(host, user, password)
            @host = host
            @user = user
            @password = password
          end
      
          private def instance_variables_to_inspect = [:@host, :@user]
        end
      
        conf = DatabaseConfig.new("localhost", "root", "hunter2")
        conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
      

      [Feature #21219]

    • Застаріла поведінка, створення процесу через Kernel#open з провідним |, була видалена. [Feature #19630]

  • Math

  • Pathname

    • Pathname було підвищено з default gem до основного класу Ruby. [Feature #17473]
  • Proc

    • Proc#parameters тепер показує анонімні необов’язкові параметри як [:opt] замість [:opt, nil], роблячи вивід узгодженим з тим, коли анонімний параметр є обов’язковим. [Bug #20974]
  • Ractor

    • Клас Ractor::Port був доданий для нового механізму синхронізації для зв’язку між Ractors. [Feature #21262]

        port1 = Ractor::Port.new
        port2 = Ractor::Port.new
        Ractor.new port1, port2 do |port1, port2|
          port1 << 1
          port2 << 11
          port1 << 2
          port2 << 12
        end
        2.times{ p port1.receive } #=> 1, 2
        2.times{ p port2.receive } #=> 11, 12
      

      Ractor::Port надає наступні методи:

      • Ractor::Port#receive
      • Ractor::Port#send (або Ractor::Port#<<)
      • Ractor::Port#close
      • Ractor::Port#closed?

      В результаті, Ractor.yield та Ractor#take були видалені.

    • Ractor#join та Ractor#value були додані для очікування завершення Ractor. Вони схожі на Thread#join та Thread#value.

    • Ractor#monitor та Ractor#unmonitor були додані як низькорівневі інтерфейси, що використовуються внутрішньо для реалізації Ractor#join.

    • Ractor.select тепер приймає лише Ractors і Ports. Якщо передані Ractors, він повертає, коли Ractor завершує роботу.

    • Ractor#default_port був доданий. Кожен Ractor має порт за замовчуванням, який використовується Ractor.send, Ractor.receive.

    • Ractor#close_incoming та Ractor#close_outgoing були видалені.

    • Ractor.shareable_proc та Ractor.shareable_lambda впроваджені для створення shareable Proc або lambda. [Feature #21550], [Feature #21557]

  • Range

    • Range#to_set тепер виконує перевірку розміру для запобігання проблемам з нескінченними діапазонами. [Bug #21654]

    • Range#overlap? тепер коректно обробляє нескінченні (необмежені) діапазони. [Bug #21185]

    • Поведінка Range#max на безпочаткових цілочисельних діапазонах була виправлена. [Bug #21174] [Bug #21175]

  • Ruby

    • Новий модуль верхнього рівня Ruby був визначений, він містить константи, пов’язані з Ruby. Цей модуль був зарезервований в Ruby 3.4 і тепер офіційно визначений. [Feature #20884]
  • Ruby::Box

    • Нова (експериментальна) функція для забезпечення розділення визначень. Для деталей про “Ruby Box”, дивіться doc/language/box.md. [Feature #21311] [Misc #21385]
  • Set

    • Set тепер є основним класом, замість класу stdlib з автозавантаженням. [Feature #21216]

    • Set#inspect тепер використовує простіше відображення, подібне до літеральних масивів. (наприклад, Set[1, 2, 3] замість #<Set: {1, 2, 3}>). [Feature #21389]

    • Передача аргументів до Set#to_set та Enumerable#to_set тепер застаріла. [Feature #21390]

  • Socket

    • Socket.tcp та TCPSocket.new приймають іменований аргумент open_timeout для вказівки тайм-ауту для початкового з’єднання. [Feature #21347]
    • Коли користувацький тайм-аут виникав у TCPSocket.new, раніше могло бути викликано або Errno::ETIMEDOUT, або IO::TimeoutError залежно від ситуації. Цю поведінку було уніфіковано, так що IO::TimeoutError тепер викликається послідовно. (Зверніть увагу, що в Socket.tcp все ще є випадки, коли Errno::ETIMEDOUT може бути викликаний у подібних ситуаціях, і що в обох випадках Errno::ETIMEDOUT може бути викликаний, коли тайм-аут виникає на рівні ОС.)
  • String

    • Оновлено Unicode до версії 17.0.0 та Emoji версії 17.0. [Feature #19908][Feature #20724][Feature #21275] (також стосується Regexp)

    • String#strip, strip!, lstrip, lstrip!, rstrip, та rstrip! розширено для прийняття аргументів *selectors. [Feature #21552]

  • Thread

    • Впроваджено підтримку аргументу Thread#raise(cause:), подібного до Kernel#raise. [Feature #21360]

Оновлення Stdlib

Ми перераховуємо лише зміни stdlib, які є помітними змінами функцій.

Інші зміни перераховані в наступних розділах. Ми також перерахували історію випусків з попередньої вбудованої версії, якою є Ruby 3.4.0, якщо вона має релізи на GitHub.

Наступні bundled gems підвищені з default gems.

Наступний default gem додано.

  • win32-registry 0.1.2

Наступні default gems оновлено.

Наступні bundled gems оновлено.

  • minitest 6.0.0
  • power_assert 3.0.1
    • 2.0.5 до [v3.0.0][power_assert-v3.0.0], [v3.0.1][power_assert-v3.0.1]
  • rake 13.3.1
    • 13.2.1 до [v13.3.0][rake-v13.3.0], [v13.3.1][rake-v13.3.1]
  • test-unit 3.7.3
    • 3.6.7 до [3.6.8][test-unit-3.6.8], [3.6.9][test-unit-3.6.9], [3.7.0][test-unit-3.7.0], [3.7.1][test-unit-3.7.1], [3.7.2][test-unit-3.7.2], [3.7.3][test-unit-3.7.3], [3.7.4][test-unit-3.7.4], [3.7.5][test-unit-3.7.5]
  • rexml 3.4.4
  • rss 0.3.2
    • 0.3.1 до [0.3.2][rss-0.3.2]
  • net-ftp 0.3.9
    • 0.3.8 до [v0.3.9][net-ftp-v0.3.9]
  • net-imap 0.6.2
    • 0.5.8 до [v0.5.9][net-imap-v0.5.9], [v0.5.10][net-imap-v0.5.10], [v0.5.11][net-imap-v0.5.11], [v0.5.12][net-imap-v0.5.12], [v0.5.13][net-imap-v0.5.13], [v0.6.0][net-imap-v0.6.0], [v0.6.1][net-imap-v0.6.1], [v0.6.2][net-imap-v0.6.2]
  • net-smtp 0.5.1
    • 0.5.0 до [v0.5.1][net-smtp-v0.5.1]
  • matrix 0.4.3
    • 0.4.2 до [v0.4.3][matrix-v0.4.3]
  • prime 0.1.4
    • 0.1.3 до [v0.1.4][prime-v0.1.4]
  • rbs 3.10.0
    • 3.8.0 до [v3.8.1][rbs-v3.8.1], [v3.9.0.dev.1][rbs-v3.9.0.dev.1], [v3.9.0.pre.1][rbs-v3.9.0.pre.1], [v3.9.0.pre.2][rbs-v3.9.0.pre.2], [v3.9.0][rbs-v3.9.0], [v3.9.1][rbs-v3.9.1], [v3.9.2][rbs-v3.9.2], [v3.9.3][rbs-v3.9.3], [v3.9.4][rbs-v3.9.4], [v3.9.5][rbs-v3.9.5], [v3.10.0.pre.1][rbs-v3.10.0.pre.1], [v3.10.0.pre.2][rbs-v3.10.0.pre.2], [v3.10.0][rbs-v3.10.0]
  • typeprof 0.31.1
  • debug 1.11.1
    • 1.11.0 до [v1.11.1][debug-v1.11.1]
  • base64 0.3.0
    • 0.2.0 до [v0.3.0][base64-v0.3.0]
  • bigdecimal 4.0.1
    • 3.1.8 до [v3.2.0][bigdecimal-v3.2.0], [v3.2.1][bigdecimal-v3.2.1], [v3.2.2][bigdecimal-v3.2.2], [v3.2.3][bigdecimal-v3.2.3], [v3.3.0][bigdecimal-v3.3.0], [v3.3.1][bigdecimal-v3.3.1], [v4.0.0][bigdecimal-v4.0.0], [v4.0.1][bigdecimal-v4.0.1]
  • drb 2.2.3
    • 2.2.1 до [v2.2.3][drb-v2.2.3]
  • syslog 0.3.0
    • 0.2.0 до [v0.3.0][syslog-v0.3.0]
  • csv 3.3.5
    • 3.3.2 до [v3.3.3][csv-v3.3.3], [v3.3.4][csv-v3.3.4], [v3.3.5][csv-v3.3.5]
  • repl_type_completor 0.1.12

RubyGems та Bundler

Ruby 4.0 постачає RubyGems та Bundler версії 4. дивіться наступні посилання для деталей.

Підтримувані платформи

  • Windows

    • Припинено підтримку версій MSVC, старіших за 14.0 (_MSC_VER 1900). Це означає, що тепер потрібен Visual Studio 2015 або новіший.

Проблеми сумісності

  • Наступні методи були видалені з Ractor через додавання Ractor::Port:

    • Ractor.yield
    • Ractor#take
    • Ractor#close_incoming
    • Ractor#close_outgoing

    [Feature #21262]

  • ObjectSpace._id2ref застарілий. [Feature #15408]

  • Process::Status#& та Process::Status#>> були видалені. Вони були застарілими в Ruby 3.3. [Bug #19868]

  • rb_path_check був видалений. Ця функція використовувалася для перевірки шляху $SAFE, яка була видалена в Ruby 2.7, і вже була застарілою. [Feature #20971]

  • Backtrace для ArgumentError про “неправильну кількість аргументів” тепер включає ім’я класу або модуля отримувача (наприклад, у Foo#bar замість у bar). [Bug #21698]

  • Backtraces більше не відображають internal кадри. Ці методи тепер виглядають так, ніби вони знаходяться у вихідному файлі Ruby, взгоджено з іншими методами, реалізованими на C. [Bug #20968]

    До:

    ruby -e '[1].fetch_values(42)'
    <internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError)
            from <internal:array>:211:in 'block in Array#fetch_values'
            from <internal:array>:211:in 'Array#map!'
            from <internal:array>:211:in 'Array#fetch_values'
            from -e:1:in '<main>'
    

    Після:

    $ ruby -e '[1].fetch_values(42)'
    -e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError)
            from -e:1:in '<main>'
    

Проблеми сумісності Stdlib

  • Бібліотека CGI видалена з default gems. Тепер ми надаємо лише cgi/escape для наступних методів:

    • CGI.escape та CGI.unescape
    • CGI.escapeHTML та CGI.unescapeHTML
    • CGI.escapeURIComponent та CGI.unescapeURIComponent
    • CGI.escapeElement та CGI.unescapeElement

    [Feature #21258]

  • З переміщенням Set зі stdlib до основного класу, set/sorted_set.rb був видалений, і SortedSet більше не є константою з автозавантаженням. Будь ласка, встановіть гем sorted_set і require 'sorted_set', щоб використовувати SortedSet. [Feature #21287]

  • Net::HTTP

    • Поведінка за замовчуванням, що автоматично встановлює заголовок Content-Type на application/x-www-form-urlencoded для запитів з тілом (наприклад, POST, PUT), коли заголовок не був явно встановлений, була видалена. Якщо ваш додаток покладався на це автоматичне значення за замовчуванням, ваші запити тепер будуть надсилатися без заголовка Content-Type, що потенційно порушить сумісність з певними серверами. [GH-net-http #205]

Оновлення API C

  • IO

    • rb_thread_fd_close застарілий і тепер нічого не робить (no-op). Якщо вам потрібно відкрити файлові дескриптори з розширень C для коду Ruby, створіть екземпляр IO, використовуючи RUBY_IO_MODE_EXTERNAL, і використовуйте rb_io_close(io) для його закриття (це також перериває та чекає на всі очікуючі операції на екземплярі IO). Пряме закриття файлових дескрипторів не перериває очікуючі операції і може призвести до невизначеної поведінки. Іншими словами, якщо два об’єкти IO спільно використовують один і той же файловий дескриптор, закриття одного не впливає на інший. [Feature #18455]
  • GVL

    • rb_thread_call_with_gvl тепер працює з або без GVL. Це дозволяє гемам уникати перевірки ruby_thread_has_gvl_p. Будь ласка, все ще будьте уважні щодо GVL. [Feature #20750]
  • Set

    • API C для Set був доданий. Наступні методи підтримуються: [Feature #21459]

      • rb_set_foreach
      • rb_set_new
      • rb_set_new_capa
      • rb_set_lookup
      • rb_set_add
      • rb_set_clear
      • rb_set_delete
      • rb_set_size

Покращення реалізації

  • Class#new (наприклад, Object.new) швидший у всіх випадках, але особливо при передачі іменованих аргументів. Це також було інтегровано в YJIT і ZJIT. [Feature #21254]
  • Купи (heaps) GC з різними розмірами пулів тепер ростуть незалежно, зменшуючи використання пам’яті, коли тільки деякі пули містять довгоживучі об’єкти
  • Очистка (sweeping) GC швидша на сторінках великих об’єктів
  • “Generic ivar” об’єкти (String, Array, TypedData, тощо) тепер використовують новий внутрішній об’єкт “fields” для швидшого доступу до змінних екземпляра
  • GC уникає підтримки внутрішньої таблиці id2ref поки вона не буде використана вперше, роблячи виділення object_id та очистку GC швидшими
  • object_id та hash швидші на об’єктах Class та Module
  • Більші bignum Integers можуть залишатися вбудованими, використовуючи виділення змінної ширини
  • Random, Enumerator::Product, Enumerator::Chain, Addrinfo, StringScanner, і деякі внутрішні об’єкти тепер захищені write-barrier, що зменшує накладні витрати GC.

Ractor

Багато роботи було зроблено, щоб зробити Ractors більш стабільними, продуктивними та придатними до використання. Ці покращення наближають реалізацію Ractor до виходу зі статусу експериментальної.

  • Покращення продуктивності
    • Заморожені рядки та таблиця символів внутрішньо використовують хеш-набір без блокування [Feature #21268]
    • Пошуки в кеші методів уникають блокування в більшості випадків
    • Доступ до змінних екземпляра класу (та generic ivar) швидший і уникає блокування
    • Конкуренція кешу CPU уникається при виділенні об’єктів шляхом використання лічильника per-ractor
    • Конкуренція кешу CPU уникається при xmalloc/xfree шляхом використання thread-local лічильника
    • object_id уникає блокування в більшості випадків
  • Виправлення помилок та стабільність
    • Виправлені можливі взаємоблокування при поєднанні Ractors та Threads
    • Виправлені проблеми з require та autoload в Ractor
    • Виправлені проблеми кодування/перекодування між Ractors
    • Виправлені гонки (race conditions) в операціях GC та інвалідації методів
    • Виправлені проблеми з процесами, що розгалужуються (forking) після запуску Ractor
    • Кількість виділень GC тепер точна під Ractors
    • Виправлено TracePoints, які не працювали після GC [Bug #19112]

JIT

  • ZJIT
    • Впроваджено експериментальний компілятор JIT на основі методів. Там, де доступно, ZJIT можна ввімкнути під час виконання за допомогою опції --zjit або викликавши RubyVM::ZJIT.enable. Для збірки Ruby з підтримкою ZJIT потрібен Rust 1.85.0 або новіший.
    • Станом на Ruby 4.0.0, ZJIT швидший за інтерпретатор, але ще не такий швидкий, як YJIT. Ми заохочуємо експериментування з ZJIT, але радимо не розгортати його у виробництві на даний момент.
    • Наша мета — зробити ZJIT швидшим за YJIT і готовим до виробництва в Ruby 4.1.
  • YJIT
    • RubyVM::YJIT.runtime_stats
      • ratio_in_yjit більше не працює в збірці за замовчуванням. Використовуйте --enable-yjit=stats при configure для ввімкнення його на --yjit-stats.
      • Додано invalidate_everything до статистики за замовчуванням, що інкрементується, коли весь код інвалідується через TracePoint.
    • Додано опції mem_size: та call_threshold: до RubyVM::YJIT.enable.
  • RJIT
    • --rjit видалено. Ми перемістимо реалізацію API стороннього JIT до репозиторію ruby/rjit.

Дивіться НОВИНИ або журнали комітів для більш деталь.

З цими змінами, 3889 файлів змінено, 230769 вставок(+), 297003 видалень(-) з моменту Ruby 3.4.0!

Веселого Різдва, щасливого Нового року та приємного хакінгу з Ruby 4.0!

Завантаження

  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.gz

    SIZE: 23955109
    SHA1: 754e39e9ad122e1b6deaed860350bac133a35ed3
    SHA256: 2e8389c8c072cb658c93a1372732d9eac84082c88b065750db1e52a5ac630271
    SHA512: 688254e939b197d564e896fb951bc1abf07142f489e91c5ed0b11f68f52d6adb6b1f86616fe03f1f0bb434beeef7e75e158b9c616afb39bb34403b0b78d2ee19
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.xz

    SIZE: 18008368
    SHA1: 05ec670e86f84325c5353ef2f2888e53b6adc602
    SHA256: a72bacee9de07283ebc19baa4ac243b193129f21aa4e168c7186fb1fe7d07fe1
    SHA512: 2d5b2e566eaf70a5f3ea6ce6afc0611c0415de58a41336ef7a0b855c9a91eda9aa790a5f8b48e40a1eb9d50f8ea0f687216e617f16c8d040a08474f3116518a4
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.zip

    SIZE: 29253204
    SHA1: 0b69f89d1d140157251c0d3a6032f6c45cdf81e8
    SHA256: 70cb1bf89279b86ab9a975d504607c051fc05ee03e311d550a5541b65e373455
    SHA512: a72e076ef618c0aeb9d20cf22e6fb12fda36809c0064ef0f98153b95a0bac257ef606342444a38f992c4594bf376a4d264686cf597463aa6f111220798784302
    

Що таке Ruby

Ruby був вперше розроблений Matz’ом (Yukihiro Matsumoto) у 1993 році, і зараз розробляється як Open Source. Він працює на багатьох платформах і використовується по всьому світу, особливо для веб-розробки.

Останні новини

Новий вигляд документації Ruby

Слідом за ре-дизайном ruby-lang.org, ми маємо більше новин, щоб відсвяткувати 30-річчя Ruby: docs.ruby-lang.org має повністю новий вигляд завдяки Aliki — новій темі за замовчуванням для...

Опублікував Stan Lo 23-12-2025

Вийшов Ruby 4.0.0 preview3

Раді повідомити про вихід Ruby 4.0.0-preview3. Ruby 4.0 вводить Ruby::Box і “ZJIT” та додає багато покращень.

Опублікував naruse 18-12-2025

Більше новин...