Ruby 4.0.0 Yayınlandı

naruse tarafından 25.12.2025 tarihinde gönderildi
Çeviri: Ender Ahmet Yurt

Ruby 4.0.0 sürümünün yayınlandığını duyurmaktan mutluluk duyuyoruz. Ruby 4.0, “Ruby Box” ve “ZJIT” sunuyor ve birçok iyileştirme ekliyor.

Ruby Box

Ruby Box, tanımlamalar hakkında ayrım sağlamak için yeni bir (deneysel) özelliktir. Ruby Box, RUBY_BOX=1 ortam değişkeni belirtildiğinde etkinleştirilir. Sınıf Ruby::Box‘tır.

Bir box içinde yüklenen tanımlamalar box içinde izole edilir. Ruby Box, monkey patch’leri, global/sınıf değişkenlerinin değişikliklerini, sınıf/modül tanımlamalarını ve yüklenmiş native/ruby kütüphanelerini diğer box’lardan izole edebilir/ayırabilir.

Beklenen kullanım durumları şunlardır:

  • Test durumları bir şeyi geçersiz kılmak için monkey patch kullandığında diğer testleri korumak için test durumlarını box içinde çalıştırma
  • Bir Ruby sürecindeki bir uygulama sunucusunda mavi-yeşil dağıtımı yürütmek için web uygulaması box’larını paralel olarak çalıştırma
  • Ruby kodu kullanarak yanıt farkını kontrol ederek belirli bir süre için bağımlılık güncellemelerini değerlendirmek için web uygulaması box’larını paralel olarak çalıştırma
  • Bir tür “paket” (üst düzey) API’sini uygulamak için temel (alt düzey) API olarak kullanılır (henüz tasarlanmamıştır)

“Ruby Box” detayı için, Ruby::Box‘a bakın. [Feature #21311] [Misc #21385]

ZJIT

ZJIT, YJIT’in yeni nesli olarak geliştirilen yeni bir tam zamanında (JIT) derleyicisidir. ZJIT desteği ile Ruby oluşturmak için Rust 1.85.0 veya daha yenisine ihtiyacınız vardır ve ZJIT, --zjit belirtildiğinde etkinleştirilir.

Ruby için yeni bir derleyici oluşturuyoruz çünkü hem performans tavanını yükseltmek (daha büyük derleme birimi boyutu ve SSA IR) hem de daha fazla dış katkıyı teşvik etmek istiyoruz (daha geleneksel bir metot derleyicisi olarak). Daha fazla ayrıntı için blog yazımıza bakın.

ZJIT yorumlayıcıdan daha hızlıdır, ancak henüz YJIT kadar hızlı değildir. ZJIT ile deneme yapmanızı öneriyoruz, ancak şimdilik onu üretime dağıtmaktan kaçının. Ruby 4.1 ZJIT için bizi takip edin.

Ractor İyileştirmeleri

Ruby’nin paralel yürütme mekanizması olan Ractor, birkaç iyileştirme aldı. Mesaj gönderme ve alma ile ilgili sorunları çözmek için yeni bir sınıf olan Ractor::Port tanıtıldı (blog yazımıza bakın). Ek olarak, Ractor.shareable_proc, Ractor’lar arasında Proc nesnelerini paylaşmayı kolaylaştırır.

Performans tarafında, birçok dahili veri yapısı, global bir kilit üzerindeki çekişmeyi önemli ölçüde azaltmak ve daha iyi paralelliğin kilidini açmak için iyileştirildi. Ractor’lar artık daha az dahili veri paylaşıyor, bu da paralel olarak çalışırken daha az CPU önbellek çekişmesi ile sonuçlanıyor.

Ractor ilk olarak Ruby 3.0’da deneysel bir özellik olarak tanıtıldı. Gelecek yıl “deneysel” durumunu kaldırmayı hedefliyoruz.

Dil değişiklikleri

  • *nil artık nil.to_a çağırmaz, benzer şekilde **nil nil.to_hash çağırmaz. [Feature #21047]

  • Bir satırın başındaki mantıksal ikili operatörler (||, &&, and ve or) önceki satırı devam ettirir, akıcı nokta gibi. Aşağıdaki kod örnekleri eşittir:

      if condition1
         && condition2
        ...
      end
    

    Önceden:

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

    [Feature #20925]

Temel sınıf güncellemeleri

Not: Yalnızca öne çıkan sınıf güncellemelerini listeliyoruz.

  • Array

    • Array#rfind, array.reverse_each.find‘a daha verimli bir alternatif olarak eklendi [Feature #21678]
    • Array#find, Enumerable#find‘ın daha verimli bir geçersiz kılması olarak eklendi [Feature #21678]
  • Binding

    • Binding#local_variables artık numaralı parametreleri içermez. Ayrıca, Binding#local_variable_get, Binding#local_variable_set ve Binding#local_variable_defined? numaralı parametreleri işlemeyi reddeder. [Bug #21049]

    • Binding#implicit_parameters, Binding#implicit_parameter_get ve Binding#implicit_parameter_defined? numaralı parametrelere ve “it” parametresine erişmek için eklendi. [Bug #21049]

  • Enumerator

    • Enumerator.produce artık enumerator’ün boyutunu belirtmek için isteğe bağlı bir size anahtar kelime argümanı kabul eder. Bu bir tamsayı, Float::INFINITY, çağrılabilir bir nesne (lambda gibi) veya bilinmeyen boyutu belirtmek için nil olabilir. Belirtilmediğinde, boyut varsayılan olarak Float::INFINITY‘dir.

        # Sonsuz enumerator
        enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
        enum.size  # => Float::INFINITY
      
        # Bilinen/hesaplanabilir boyuta sahip sonlu enumerator
        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

    • Bir ArgumentError yükseldiğinde, artık hem metot çağrısı (çağıran) hem de metot tanımı (çağrılan) için kod parçacıkları görüntüler. [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

    • Kernel#raise‘e benzer şekilde Fiber#raise(cause:) argümanı için destek tanıtıldı. [Feature #21360]
  • Fiber::Scheduler

    • Bir fiber’ı verilen istisna ile kesmek için Fiber::Scheduler#fiber_interrupt tanıtıldı. İlk kullanım durumu, IO işlemi kapatıldığında engelleyici bir IO işleminde bekleyen bir fiber’ı kesmektir. [Feature #21166]

    • Sinyal istisnaları devre dışı bırakıldığında fiber zamanlayıcının işlemeye devam etmesine izin vermek için Fiber::Scheduler#yield tanıtıldı. [Bug #21633]

    • Asenkron IO#close için Fiber::Scheduler#io_close hook’u yeniden tanıtıldı.

    • IO yazma arabelleğini boşaltırken Fiber::Scheduler#io_write çağrıldı. [Bug #21789]

  • File

    • File::Stat#birthtime artık Linux’ta çekirdek ve dosya sistemi tarafından desteklendiğinde statx sistem çağrısı aracılığıyla kullanılabilir. [Feature #21205]
  • IO

    • IO.select zaman aşımı argümanı olarak Float::INFINITY kabul eder. [Feature #20610]

    • Kullanımdan kaldırılan bir davranış, IO sınıfı metodları ile öndeki | ile süreç oluşturma, kaldırıldı. [Feature #19630]

  • Kernel

    • Kernel#inspect artık #inspect dizesinde hangi örnek değişkenlerinin görüntüleneceğini kontrol etmeye izin veren bir #instance_variables_to_inspect metodunun varlığını kontrol eder:

        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]

    • Kullanımdan kaldırılan bir davranış, Kernel#open ile öndeki | ile süreç oluşturma, kaldırıldı. [Feature #19630]

  • Math

  • Pathname

    • Pathname varsayılan bir gem’den Ruby’nin temel bir sınıfına yükseltildi. [Feature #17473]
  • Proc

    • Proc#parameters artık anonim isteğe bağlı parametreleri [:opt, nil] yerine [:opt] olarak gösterir, bu da çıktıyı anonim parametre gerekli olduğundaki ile tutarlı hale getirir. [Bug #20974]
  • Ractor

    • Ractor’lar arasında iletişim kurmak için yeni bir senkronizasyon mekanizması için Ractor::Port sınıfı eklendi. [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 aşağıdaki metodları sağlar:

      • Ractor::Port#receive
      • Ractor::Port#send (veya Ractor::Port#<<)
      • Ractor::Port#close
      • Ractor::Port#closed?

      Sonuç olarak, Ractor.yield ve Ractor#take kaldırıldı.

    • Bir Ractor’ın sonlandırılmasını beklemek için Ractor#join ve Ractor#value eklendi. Bunlar Thread#join ve Thread#value‘ya benzer.

    • Ractor#join‘i uygulamak için dahili olarak kullanılan alt düzey arayüzler olarak Ractor#monitor ve Ractor#unmonitor eklendi.

    • Ractor.select artık yalnızca Ractor’ları ve Port’ları kabul eder. Ractor’lar verilirse, bir Ractor sonlandığında döner.

    • Ractor#default_port eklendi. Her Ractor‘ın, Ractor.send, Ractor.receive tarafından kullanılan bir varsayılan portu vardır.

    • Ractor#close_incoming ve Ractor#close_outgoing kaldırıldı.

    • Paylaşılabilir Proc veya lambda yapmak için Ractor.shareable_proc ve Ractor.shareable_lambda tanıtıldı. [Feature #21550], [Feature #21557]

  • Range

    • Range#to_set artık sonsuz aralıklarla ilgili sorunları önlemek için boyut kontrolleri yapar. [Bug #21654]

    • Range#overlap? artık sonsuz (sınırsız) aralıkları doğru şekilde işler. [Bug #21185]

    • Başlangıçsız tamsayı aralıklarında Range#max davranışı düzeltildi. [Bug #21174] [Bug #21175]

  • Ruby

    • Ruby ile ilgili sabitleri içeren yeni bir üst düzey Ruby modülü tanımlandı. Bu modül Ruby 3.4’te ayrıldı ve şimdi resmi olarak tanımlandı. [Feature #20884]
  • Ruby::Box

  • Set

    • Set artık otomatik yüklenen bir stdlib sınıfı yerine temel bir sınıftır. [Feature #21216]

    • Set#inspect artık literal dizilere benzer şekilde daha basit bir görüntü kullanır. (örn. #<Set: {1, 2, 3}> yerine Set[1, 2, 3]). [Feature #21389]

    • Set#to_set ve Enumerable#to_set‘e argüman geçirmek artık kullanımdan kaldırıldı. [Feature #21390]

  • Socket

    • Socket.tcp ve TCPSocket.new, ilk bağlantı için zaman aşımını belirtmek için open_timeout anahtar kelime argümanını kabul eder. [Feature #21347]
    • TCPSocket.new‘de kullanıcı tarafından belirtilen bir zaman aşımı oluştuğunda, daha önce duruma bağlı olarak Errno::ETIMEDOUT veya IO::TimeoutError yükseltilebilirdi. Bu davranış, artık IO::TimeoutError‘ın tutarlı bir şekilde yükseltilmesi için birleştirildi. (Lütfen Socket.tcp‘de, benzer durumlarda hala Errno::ETIMEDOUT‘un yükseltilebileceği durumlar olduğunu ve her iki durumda da zaman aşımı işletim sistemi düzeyinde oluştuğunda Errno::ETIMEDOUT‘un yükseltilebileceğini unutmayın.)
  • String

    • Unicode, Versiyon 17.0.0’a ve Emoji Versiyon 17.0’a güncellendi. [Feature #19908][Feature #20724][Feature #21275] (Regexp için de geçerlidir)

    • String#strip, strip!, lstrip, lstrip!, rstrip ve rstrip! *selectors argümanlarını kabul edecek şekilde genişletildi. [Feature #21552]

  • Thread

    • Kernel#raise‘e benzer şekilde Thread#raise(cause:) argümanı için destek tanıtıldı. [Feature #21360]

Stdlib güncellemeleri

Yalnızca önemli özellik değişiklikleri olan stdlib değişikliklerini listeliyoruz.

Diğer değişiklikler aşağıdaki bölümlerde listelenmiştir. Ayrıca GitHub sürümleri varsa, önceki paketlenmiş sürüm olan Ruby 3.4.0’dan yayın geçmişini listeledik.

Aşağıdaki paketlenmiş gem’ler varsayılan gem’lerden yükseltildi.

Aşağıdaki varsayılan gem eklendi.

  • win32-registry 0.1.2

Aşağıdaki varsayılan gem’ler güncellendi.

Aşağıdaki paketlenmiş gem’ler güncellendi.

RubyGems ve Bundler

Ruby 4.0, RubyGems ve Bundler sürüm 4’ü paketledi. Detaylar için aşağıdaki bağlantılara bakın.

Desteklenen platformlar

  • Windows

    • 14.0’dan (_MSC_VER 1900) eski MSVC sürümleri için destek kaldırıldı. Bu, artık Visual Studio 2015 veya daha yenisinin gerekli olduğu anlamına gelir.

Uyumluluk sorunları

  • Ractor::Port eklenmesi nedeniyle aşağıdaki metodlar Ractor’dan kaldırıldı:

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

    [Feature #21262]

  • ObjectSpace._id2ref kullanımdan kaldırıldı. [Feature #15408]

  • Process::Status#& ve Process::Status#>> kaldırıldı. Ruby 3.3’te kullanımdan kaldırılmışlardı. [Bug #19868]

  • rb_path_check kaldırıldı. Bu fonksiyon, Ruby 2.7’de kaldırılan $SAFE yol kontrolü için kullanılıyordu ve zaten kullanımdan kaldırılmıştı. [Feature #20971]

  • “Yanlış sayıda argüman” ArgumentError‘ı için geri izleme artık alıcının sınıf veya modül adını içerir (örneğin, bar‘da yerine Foo#bar‘da). [Bug #21698]

  • Geri izlemeler artık internal çerçevelerini görüntülemiyor. Bu metodlar artık Ruby kaynak dosyasındaymış gibi görünür, diğer C ile uygulanan metodlarla tutarlı. [Bug #20968]

    Önce:

    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>'
    

    Sonra:

    $ 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 uyumluluk sorunları

  • CGI kütüphanesi varsayılan gem’lerden kaldırıldı. Şimdi yalnızca aşağıdaki metodlar için cgi/escape sağlıyoruz:

    • CGI.escape ve CGI.unescape
    • CGI.escapeHTML ve CGI.unescapeHTML
    • CGI.escapeURIComponent ve CGI.unescapeURIComponent
    • CGI.escapeElement ve CGI.unescapeElement

    [Feature #21258]

  • Set‘in stdlib’den temel sınıfa taşınmasıyla birlikte, set/sorted_set.rb kaldırıldı ve SortedSet artık otomatik yüklenen bir sabit değil. Lütfen sorted_set gem’ini yükleyin ve SortedSet kullanmak için require 'sorted_set' yapın. [Feature #21287]

  • Net::HTTP

    • Başlık açıkça ayarlanmadığında gövdeli istekler (örneğin, POST, PUT) için otomatik olarak Content-Type başlığını application/x-www-form-urlencoded olarak ayarlama varsayılan davranışı kaldırıldı. Uygulamanız bu otomatik varsayılana güveniyorsa, istekleriniz artık Content-Type başlığı olmadan gönderilecek ve potansiyel olarak belirli sunucularla uyumluluğu bozacaktır. [GH-net-http #205]

C API güncellemeleri

  • IO

    • rb_thread_fd_close kullanımdan kaldırıldı ve artık işlemsizdir. Dosya tanımlayıcılarını C uzantılarından Ruby koduna açmanız gerekiyorsa, RUBY_IO_MODE_EXTERNAL kullanarak bir IO örneği oluşturun ve kapatmak için rb_io_close(io) kullanın (bu aynı zamanda IO örneğindeki tüm bekleyen işlemleri keser ve bekler). Dosya tanımlayıcılarını doğrudan kapatmak bekleyen işlemleri kesmez ve tanımsız davranışlara yol açabilir. Başka bir deyişle, iki IO nesnesi aynı dosya tanımlayıcısını paylaşıyorsa, birini kapatmak diğerini etkilemez. [Feature #18455]
  • GVL

    • rb_thread_call_with_gvl artık GVL ile veya GVL olmadan çalışır. Bu, gem’lerin ruby_thread_has_gvl_p kontrolünden kaçınmasına olanak tanır. Lütfen hala GVL konusunda dikkatli olun. [Feature #20750]
  • Set

    • Set için bir C API’si eklendi. Aşağıdaki metodlar desteklenir: [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

Uygulama iyileştirmeleri

  • Class#new (örn. Object.new) tüm durumlarda daha hızlıdır, ancak özellikle anahtar kelime argümanları geçirirken. Bu aynı zamanda YJIT ve ZJIT’e de entegre edilmiştir. [Feature #21254]
  • Farklı boyut havuzlarının GC yığınları artık bağımsız olarak büyür, bu da yalnızca bazı havuzlar uzun ömürlü nesneler içerdiğinde bellek kullanımını azaltır
  • GC süpürmesi büyük nesnelerin sayfalarında daha hızlıdır
  • “Genel ivar” nesneleri (String, Array, TypedData, vb.) artık daha hızlı örnek değişken erişimi için yeni bir dahili “fields” nesnesi kullanır
  • GC, ilk kez kullanılana kadar dahili bir id2ref tablosunu tutmaktan kaçınır, object_id tahsisini ve GC süpürmesini daha hızlı hale getirir
  • object_id ve hash, Class ve Module nesnelerinde daha hızlıdır
  • Daha büyük bignum Integer’lar değişken genişlik tahsisi kullanarak gömülü kalabilir
  • Random, Enumerator::Product, Enumerator::Chain, Addrinfo, StringScanner ve bazı dahili nesneler artık yazma engelleyici korumalıdır, bu da GC yükünü azaltır.

Ractor

Ractor’ları daha kararlı, performanslı ve kullanılabilir hale getirmek için çok sayıda çalışma yapıldı. Bu iyileştirmeler Ractor uygulamasını deneysel durumdan çıkarmaya daha yaklaştırıyor.

  • Performans iyileştirmeleri
    • Donmuş dizeler ve sembol tablosu dahili olarak kilitsiz bir hash seti kullanır [Feature #21268]
    • Metot önbellek aramaları çoğu durumda kilitlemeyi önler
    • Class (ve genel ivar) örnek değişken erişimi daha hızlıdır ve kilitlemeyi önler
    • CPU önbellek çekişmesi, ractor başına bir sayaç kullanılarak nesne tahsisinde önlenir
    • CPU önbellek çekişmesi, iş parçacığı yerel bir sayaç kullanılarak xmalloc/xfree’de önlenir
    • object_id çoğu durumda kilitlemeyi önler
  • Hata düzeltmeleri ve kararlılık
    • Ractor’lar ve Thread’leri birleştirirken olası kilitlenmeler düzeltildi
    • Bir Ractor’da require ve autoload ile ilgili sorunlar düzeltildi
    • Ractor’lar arasında kodlama/dönüştürme sorunları düzeltildi
    • GC işlemlerinde ve metot geçersiz kılmada yarış koşulları düzeltildi
    • Bir Ractor başlatıldıktan sonra çatallanma işlemleriyle ilgili sorunlar düzeltildi
    • GC tahsis sayıları artık Ractor’lar altında doğrudur
    • GC’den sonra TracePoint’lerin çalışmaması düzeltildi [Bug #19112]

JIT

  • ZJIT
    • Bir deneysel metot tabanlı JIT derleyicisi tanıtıldı. Mevcut olduğunda, ZJIT çalışma zamanında --zjit seçeneği ile veya RubyVM::ZJIT.enable çağrılarak etkinleştirilebilir. Ruby oluştururken, ZJIT desteğini dahil etmek için Rust 1.85.0 veya daha yenisi gereklidir.
    • Ruby 4.0.0 itibariyle, ZJIT yorumlayıcıdan daha hızlıdır, ancak henüz YJIT kadar hızlı değildir. ZJIT ile deneme yapmanızı öneriyoruz, ancak şimdilik onu üretime dağıtmamanızı öneririz.
    • Hedefimiz ZJIT’i YJIT’ten daha hızlı ve üretime hazır hale getirmek Ruby 4.1’de.
  • YJIT
    • RubyVM::YJIT.runtime_stats
      • ratio_in_yjit artık varsayılan yapıda çalışmaz. --yjit-stats‘ta etkinleştirmek için configure‘da --enable-yjit=stats kullanın.
      • TracePoint tarafından her kod geçersiz kılındığında artırılan invalidate_everything varsayılan istatistiklere eklendi.
    • RubyVM::YJIT.enable‘a mem_size: ve call_threshold: seçenekleri eklendi.
  • RJIT
    • --rjit kaldırıldı. Üçüncü taraf JIT API’sinin uygulamasını ruby/rjit deposuna taşıyacağız.

Daha fazla ayrıntı için NEWS veya commit loglarına bakın.

Bu değişikliklerle, Ruby 3.4.0’dan bu yana 3889 dosya değişti, 230769 ekleme(+), 297003 silme(-)!

Mutlu Noeller, Mutlu Yıllar ve Ruby 4.0 ile Mutlu Hackleme!

İndir

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

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

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

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

Ruby nedir

Ruby ilk olarak 1993 yılında Matz (Yukihiro Matsumoto) tarafından geliştirildi ve şimdi Açık Kaynak olarak geliştirilmektedir. Birçok platformda çalışır ve özellikle web geliştirme için tüm dünyada kullanılır.

Son Haberler

Dahası...