1 पॉइंट द्वारा GN⁺ 5 일 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Ruby कोड को standalone native binary में बदलता है, और पूरे प्रोग्राम-स्तर की type inference व C code generation के जरिए नवीनतम CRuby miniruby की तुलना में geometric mean पर लगभग 11.6x तेज़ execution का लक्ष्य रखता है
  • कंपाइल पाइपलाइन Prism-आधारित parser से Ruby को AST text में बदलने के बाद self-hosting backend के जरिए type inference और C code generation करती है, फिर standard C compiler से standalone binary बनाती है
  • compiler backend Ruby में लिखा गया self-hosting architecture रखता है, और bootstrap प्रक्रिया के बाद gen2.c == gen3.c स्थापित होता है, जिससे अपने-आप को फिर से compile करने वाला loop बंद हो जाता है
  • string concat flattening, value-type promotion, loop-invariant length hoisting, static symbol interning, bigint auto-promotion जैसे compile-time optimization शामिल हैं, और built-in regexp engine, bigint, तथा single-header runtime के जरिए बाहरी runtime dependency कम की जाती है
  • eval, metaprogramming, Thread, और सामान्य encoding handling समर्थित नहीं हैं, लेकिन Ruby के बिना चलने वाले deployment form और compute-intensive workload में बड़े performance अंतर Ruby AOT compilation की व्यावहारिकता दिखाते हैं

यह कैसे काम करता है

  • कंपाइल पाइपलाइन Ruby file को parse करके AST text file में serialize करती है, फिर type inference और C code generation के बाद standard C compiler से native binary बनाती है
  • spinel_parse Prism और libprism का उपयोग करके Ruby को parse करता है, और जब C binary उपलब्ध न हो तो CRuby और Prism gem का उपयोग करने वाला fallback path अपनाता है
  • spinel_codegen self-hosted native binary के रूप में चलता है, AST लेकर type inference + C code generation करता है
  • अंतिम चरण cc -O2 -Ilib -lm के साथ C source और runtime header को compile करता है, और परिणामस्वरूप binary standalone रूप में बनती है

Self-Hosting

  • bootstrap chain CRuby + spinel_parse.rb से AST बनाती है, CRuby + spinel_codegen.rb से gen1.c और bin1 बनाती है, और फिर बने हुए binary से gen2.c, gen3.c बनाकर loop बंद करती है
  • gen2.c == gen3.c यह स्पष्ट करता है कि bootstrap loop बंद हो चुका है
  • backend spinel_codegen.rb Spinel द्वारा सीधे compile किए जा सकने वाले Ruby subset में लिखा गया है
    • classes, def, attr_accessor
    • if/case/while
    • each/map/select, yield
    • begin/rescue
    • String, Array, Hash operations और File I/O
  • backend में metaprogramming, eval, require शामिल नहीं हैं

प्रदर्शन और बेंचमार्क

  • टेस्ट में 74 पास, बेंचमार्क में 55 पास की स्थिति है
  • 28 benchmarks के आधार पर geometric mean नवीनतम CRuby miniruby की तुलना में लगभग 11.6x तेज़ है
  • तुलना का आधार bundled gem के बिना बना नवीनतम CRuby miniruby build है, और system ruby 3.2.3 से भी तेज़ baseline के मुकाबले compute-intensive workload में बढ़त बड़ी है
  • computation performance

    • life 20ms बनाम 1,733ms, यानी 86.7x तेज़
    • ackermann 5ms बनाम 374ms, यानी 74.8x तेज़
    • mandelbrot 25ms बनाम 1,453ms, यानी 58.1x तेज़
    • recursive fib version 17ms बनाम 581ms, यानी 34.2x तेज़
    • nqueens 10ms बनाम 304ms, यानी 30.4x तेज़
    • tarai 16ms बनाम 461ms, यानी 28.8x तेज़
    • tak 22ms बनाम 532ms, यानी 24.2x तेज़
    • matmul 13ms बनाम 313ms, यानी 24.1x तेज़
    • sudoku 6ms बनाम 102ms, यानी 17.0x तेज़
    • partial_sums 93ms बनाम 1,498ms, यानी 16.1x तेज़
    • fannkuch 2ms बनाम 19ms, यानी 9.5x तेज़
    • sieve 39ms बनाम 332ms, यानी 8.5x तेज़
    • fasta 3ms बनाम 21ms, यानी 7.0x तेज़
  • data structures और GC

    • rbtree 24ms बनाम 543ms, यानी 22.6x तेज़
    • splay tree 14ms बनाम 195ms, यानी 13.9x तेज़
    • huffman 6ms बनाम 59ms, यानी 9.8x तेज़
    • so_lists 76ms बनाम 410ms, यानी 5.4x तेज़
    • binary_trees 11ms बनाम 40ms, यानी 3.6x तेज़
    • linked_list 136ms बनाम 388ms, यानी 2.9x तेज़
    • gcbench 1,845ms बनाम 3,641ms, यानी 2.0x तेज़
  • वास्तविक प्रोग्राम

    • json_parse 39ms बनाम 394ms, यानी 10.1x तेज़
    • bigint_fib में 1000-digit calculation 2ms बनाम 16ms, यानी 8.0x तेज़
    • ao_render 417ms बनाम 3,334ms, यानी 8.0x तेज़
    • pidigits 2ms बनाम 13ms, यानी 6.5x तेज़
    • str_concat 2ms बनाम 13ms, यानी 6.5x तेज़
    • template engine 152ms बनाम 936ms, यानी 6.2x तेज़
    • csv_process 234ms बनाम 860ms, यानी 3.7x तेज़
    • io_wordcount 33ms बनाम 97ms, यानी 2.9x तेज़

समर्थित Ruby फीचर

  • Core फीचर के रूप में classes, inheritance, super, include mixin, attr_accessor, Struct.new, alias, module constants, और built-in types के लिए open classes समर्थित हैं
  • Control Flow में if/elsif/else, unless, case/when, case/in pattern matching, while, until, loop, for..in, break, next, return, catch/throw, &. समर्थित हैं
  • Blocks में yield, block_given?, &block, proc {}, Proc.new, -> x { }, method(:name) समर्थित हैं, और each, map, select, reduce, sort_by, times, upto, downto जैसे block methods भी शामिल हैं
  • Exceptions में begin/rescue/ensure/retry, raise, और user-defined exception classes समर्थित हैं
  • Types में Integer, Float, String, Array, Hash, Range, Time, StringIO, File, Regexp, Bigint, Fiber शामिल हैं
    • polymorphic values को tagged unions के रूप में संभाला जाता है
    • self-referential data structures के लिए nullable object types T? दिए गए हैं
  • Global Variables में $name को static C variables के रूप में compile किया जाता है, और type mismatch compile time पर पकड़ा जाता है
  • I/O में puts, print, printf, p, gets, ARGV, ENV[], File.read/write/open, system(), backticks समर्थित हैं

string, regexp, symbol, Bigint, Fiber

  • Strings immutable और mutable strings दोनों को संभालते हैं, और << अपने-आप mutable string sp_String में promote होकर O(n) in-place append करता है
  • +, interpolation, tr, ljust/rjust/center और standard methods दोनों string representations पर काम करते हैं
  • s[i] == "c" जैसी तुलना सीधे char array access के लिए optimize की जाती है, इसलिए बिना allocation के काम होता है
  • a + b + c + d जैसे concat को एक बार के sp_str_concat4 या sp_str_concat_arr call में flatten किया जाता है, जिससे N-1 कम allocation होते हैं
  • loop के अंदर str.split(sep) उसी sp_StrArray को बार-बार reuse करता है, और csv_process में 40 लाख allocations हट जाते हैं
  • Regexp बाहरी dependency के बिना built-in NFA regexp engine का उपयोग करता है
    • =~, $1-$9, match?, gsub, sub, scan, split समर्थित हैं
  • Bigint mruby-bigint आधारित arbitrary-precision integers का उपयोग करता है
    • q = q * k जैसे loop multiplication patterns में auto-promotion होता है
    • static library के रूप में link होता है और केवल वास्तविक उपयोग पर शामिल किया जाता है
  • Fiber ucontext_t आधारित cooperative concurrency देता है
    • Fiber.new, Fiber#resume, Fiber.yield और value passing समर्थित हैं
    • free variables को heap-promoted cells के रूप में capture किया जाता है
  • Symbols string से अलग sp_sym type के रूप में implemented हैं
    • :a != "a" बना रहता है
    • symbol literals compile time पर intern होकर SPS_name constants बनते हैं
    • String#to_sym केवल ज़रूरत पड़ने पर dynamic pool का उपयोग करता है
    • symbol-key hash sp_SymIntHash का उपयोग करता है, जो string की जगह integer keys सीधे store करता है, इसलिए strcmp और dynamic string allocation समाप्त हो जाते हैं

memory management और value types

  • memory management में mark-and-sweep GC का उपयोग होता है, जिसमें size-segregated free lists, non-recursive marking, sticky mark bits शामिल हैं
  • छोटे और सरल classes को अपने-आप value types में promote कर stack पर रखा जाता है
    • शर्तें: 8 या उससे कम scalar fields
    • inheritance नहीं
    • parameters के ज़रिए mutation नहीं
  • 5-field class की 10 लाख allocations 85ms से घटकर 2ms हो जाती हैं
  • केवल value types इस्तेमाल करने वाले प्रोग्राम GC runtime को बिल्कुल export नहीं करते

optimization

  • पूरे प्रोग्राम-स्तर की type inference के आधार पर कई compile-time optimization किए जाते हैं
  • Value-type promotion के जरिए छोटे immutable classes C struct stack objects बन जाते हैं, जिससे GC overhead हट जाता है
  • Constant propagation में N = 100 जैसे simple literal constants cst_N lookup के बिना सीधे use site पर inline हो जाते हैं
  • Loop-invariant length hoisting में while i < arr.length के लिए length loop से पहले केवल एक बार निकाली जाती है
    • अगर body में arr.push की तरह receiver object बदलता है, तो यह hoist निष्क्रिय हो जाता है
  • Method inlining छोटे, non-recursive, 3 statements तक वाले methods पर static inline लगाकर gcc inlining को प्रोत्साहित करता है
  • String concat chain flattening concat chain को single call में बदलकर intermediate string creation हटाता है
  • Bigint auto-promotion self-referential addition या repeated multiplication patterns को अपने-आप bigint में promote करता है
  • Bigint to_s mruby-bigint के mpz_get_str का उपयोग करके divide-and-conquer O(n log²n) में चलता है
  • Static symbol interning "literal".to_sym को compile-time SPS_<name> constant में बदलता है, और dynamic interning होने पर ही runtime pool जोड़ता है
  • sub_range में length-hoisted string sp_str_sub_range_len का उपयोग करती है, जिससे अंदरूनी strlen call छूट जाता है
  • loop के अंदर line.split(",") मौजूदा sp_StrArray को reuse करता है
  • Dead-code elimination -ffunction-sections -fdata-sections और --gc-sections के जरिए इस्तेमाल न होने वाले runtime functions को final binary से हटा देता है
  • Iterative inference early exit में param, return, ivar के 3 signature arrays में बदलाव रुकते ही fixed-point loop तुरंत रोक दिया जाता है
    • अधिकांश प्रोग्राम 4 full iterations की जगह 1–2 iterations में converge करते हैं
    • bootstrap time लगभग 14% कम हो जाता है
  • parse_id_list byte walk self-compile के दौरान लगभग 1.2 लाख बार बुलाए जाने वाले AST field list parser में s.split(",") की जगह s.bytes[i] manual traversal उपयोग करता है, जिससे प्रति call allocation N+1 से घटकर 2 रह जाती है
  • generated C code default warning level पर warning-free build बनाए रखता है, और harness -Werror का उपयोग करके regression तुरंत सामने लाता है

architecture

  • repository structure निम्न हिस्सों में बंटी है
    • spinel: POSIX shell आधारित one-command wrapper script
    • spinel_parse.c: libprism से text AST तक जाने वाला C frontend, 1,061 lines
    • spinel_codegen.rb: AST से C code तक जाने वाला compiler backend, 21,109 lines
    • lib/sp_runtime.h: runtime library header, 581 lines
    • lib/sp_bigint.c: arbitrary-precision integer, 5,394 lines
    • lib/regexp/: built-in regexp engine, 1,759 lines
    • test/: 74 functional tests
    • benchmark/: 55 benchmarks
    • Makefile: build automation
  • runtime lib/sp_runtime.h GC, array/hash/string implementation और अन्य runtime support को एक header file में रखता है
  • generated C code इस header को include करता है, और linker libspinel_rt.a से केवल ज़रूरी हिस्से लाता है
    • bigint
    • regexp engine
  • parser के दो implementations हैं
    • spinel_parse.c libprism को सीधे link करके CRuby के बिना चलता है
    • spinel_parse.rb Prism gem का उपयोग करने वाला CRuby fallback है
  • दोनों parser समान AST output बनाते हैं, और spinel wrapper संभव हो तो C binary को प्राथमिकता देता है
  • require_relative parsing stage पर resolve होकर referenced files inline कर दिए जाते हैं

सीमाएँ

  • No eval: eval, instance_eval, class_eval समर्थित नहीं हैं
  • No metaprogramming: send, method_missing, dynamic define_method समर्थित नहीं हैं
  • No threads: Thread, Mutex समर्थित नहीं; केवल Fiber समर्थित है
  • No encoding: UTF-8 और ASCII मानकर चलता है
  • No general lambda calculus: गहराई से nested -> x { } और [] calls को handle नहीं करता

dependencies और execution model

  • build-time dependencies में libprism C library और शुरुआती bootstrap के लिए CRuby शामिल हैं
  • runtime dependency नहीं है, और generated binary को केवल libc + libm चाहिए
  • regexp built-in engine का उपयोग करता है, इसलिए बाहरी library की ज़रूरत नहीं होती
  • Bigint built-in है, लेकिन केवल वास्तविक उपयोग पर link होता है
  • Prism वह Ruby parser है जिसका उपयोग spinel_parse करता है
    • make deps rubygems.org से prism gem tarball डाउनलोड करके C source को vendor/prism में extract करता है
    • अगर prism gem पहले से installed हो तो इसे अपने-आप detect कर लिया जाता है
    • PRISM_DIR=/path/to/prism के जरिए custom path भी दिया जा सकता है
  • CRuby केवल शुरुआती bootstrap के लिए चाहिए; make के बाद पूरी पाइपलाइन Ruby के बिना चलती है

प्रोजेक्ट इतिहास

  • Spinel शुरू में C में implement किया गया था, इसका आकार 18K lines था, और यह c-version branch में मौजूद है
  • इसके बाद Ruby में दोबारा लिखा गया ruby-v1 branch आया
  • वर्तमान master self-hosting सक्षम Ruby subset में दोबारा लिखे गए version का प्रतिनिधित्व करता है

लाइसेंस

  • MIT License का उपयोग किया जाता है
  • LICENSE file का पालन करता है

1 टिप्पणियां

 
GN⁺ 5 일 전
Hacker News टिप्पणियाँ
  • अगर यह Matz ने बनाया है, तो उन्हें Ruby semantics की सीमाएँ भी अच्छी तरह पता होंगी, इसलिए इस पर भरोसा होता है
    मेरा मास्टर्स थीसिस भी AOT JS compiler पर था, और वह चलता तो था, लेकिन input data पर इतनी पाबंदियाँ थीं कि आखिरकार छोड़ना पड़ा
    उस समय JS developers खुद इस तरह की पाबंदियों का लगातार पालन करने के आदी नहीं थे, और JSON.parse जैसी मूल रूप से unknowable input बड़ी बाधा थी
    अब TypeScript की वजह से यह तब की तुलना में कहीं ज़्यादा व्यावहारिक हो सकता है
    सिर्फ सामान्य lambda calculus को देखें तो भी type inference की सीमाएँ साफ हैं, और Matt Might के papers या Shed-skin Python के काम में भी ऐसी ही पाबंदियाँ दिखती हैं
    मुझे जिज्ञासा है कि असली Ruby code में eval, send, method_missing, define_method कितने आम हैं, और बिना type वाली parsing, जैसे JSON input, आम तौर पर कैसे संभाली जाती है

    • यह डिज़ाइन काफ़ी pragmatic लगती है
      Ruby parsing, translation से भी ज़्यादा कठिन है, इसलिए इसमें Prism इस्तेमाल किया गया है, और output C generate होता है
      Ruby semantics का बेसिक हिस्सा अपने आप में इतना मुश्किल नहीं है
      दूसरी तरफ मैं एक पुराने self-hosting AOT compiler पर काम कर रहा हूँ जो pure Ruby में लिखा है, और उसने अपना parser बनाने की ज़िद करके जानबूझकर कहीं ज़्यादा कठिन रास्ता चुना
      शुरुआत के 80% में ही यह सीख लिया था कि मोटा-मोटी बनाकर भी काफ़ी Ruby code चलाया जा सकता है, और असल मुश्किल वाला "दूसरा 80%" उन चीज़ों में जमा है जिन्हें Matz ने इस प्रोजेक्ट और mruby से बाहर रखा है, जैसे encoding और तरह-तरह की peripheral सुविधाएँ
      ईमानदारी से कहूँ तो Ruby में कई ऐसी सुविधाएँ भी हैं जिन्हें मैंने असली code में कभी नहीं देखा, इसलिए कुछ अगर deprecated भी हो जाएँ तो मुझे अजीब नहीं लगेगा
      send, method_missing, define_method बहुत आम हैं
      पाबंदियाँ mruby जैसी हैं, और उन पाबंदियों के भीतर भी इसके उपयोग मौजूद हैं
      send, method_missing, define_method का support देना अपेक्षाकृत आसान है
      लेकिन eval() support करना बेहद दर्दनाक है
      फिर भी Ruby में eval() का बड़ा हिस्सा statically instance_eval के block version में घटाया जा सकता है, और ऐसे मामलों में AOT compilation काफ़ी आसान हो जाती है
      उदाहरण के लिए, अगर eval() में जाने वाली string को statically जाना या तोड़ा जा सके, तो समाधान की गुंजाइश बहुत बढ़ जाती है
      असल में eval() का बहुत-सा उपयोग अनावश्यक होता है या सिर्फ साधारण introspection workaround जैसा होता है, इसलिए static analysis से संभाला जा सकता है
      अगर मेरे compiler में वही bottleneck निकला, तो मैं वहीं से काम शुरू करूँगा
    • Rails-style magic बनाने के लिए ऐसी सुविधाएँ काफ़ी ज़रूरी होती हैं
      बिना type वाला JSON ingestion भी शायद इन्हीं mechanisms का इस्तेमाल करता होगा
      इन्हें हटाने पर Crystal जितना strongly typed नहीं, लेकिन आधिकारिक Ruby जितना metaprogramming-निर्भर भी नहीं, ऐसी एक छोटी और पढ़ने में आसान भाषा बचती है
      इसलिए इसमें काफ़ी potential दिखता है, लेकिन आखिरकार समय के साथ ही पता चलेगा
    • अगर Ruby को Objective-C में compile किया जाए, तो शायद Ruby की सारी सुविधाओं को support करते हुए भी interpreter Ruby से तेज़ बनाया जा सकता है
    • मैं eval का अक्सर इस्तेमाल करने वालों में हूँ
      इसके बिना काम चल सकता है, लेकिन मेरे लिए वह ज़्यादा ergonomic है
    • मेरे अनुभव में दिलचस्प चीज़ें eval, exec, define_method, और Class.new, Struct.new से नई classes बनाने वाले patterns हैं
      इनका ज़्यादातर उपयोग app boot के समय या files require करते समय होता है, और एक अर्थ में वह पहले से ही compilation stage जैसा है
  • यह वही है जिसे Matz ने अभी RubyKaigi 2026 में पेश किया
    यह experimental है, लेकिन Claude की मदद से लगभग एक महीने में बनाया गया, और live demo भी सफल रहा
    इसका नाम Matz की नई बिल्ली के नाम पर रखा गया है, और उस बिल्ली का नाम Card Captor Sakura की बिल्ली के नाम से आया है, जहाँ वह Ruby नाम वाले character के साथ जोड़ी बनाती है

    • लोग बहुत कहते हैं कि AI शुरू से अंत तक पूरा program बना देगा, लेकिन मुझे ज़्यादा यथार्थवादी scenario यह लगता है कि वह 10x programmer को 100x programmer बना दे
      Matz जैसे व्यक्ति के लिए यह शायद 100x को 500x तक धकेलने जैसा हो सकता है
    • मेरे दिमाग़ में Spinel का सबसे ताज़ा संदर्भ Steven Universe वाला था, इसलिए Spinel/Ruby (Moon) pun मुझे बिल्कुल समझ नहीं आया, लेकिन अब समझ आया तो दिन बन गया
    • मैंने तो स्वाभाविक रूप से mineral spinel ही सोचा था :)
      https://en.wikipedia.org/wiki/Spinel
    • धन्यवाद
      लगता है वीडियो अभी live नहीं है, और शायद इस चैनल पर एक-एक करके आ रहे हैं
      https://www.youtube.com/@rubykaigi4884/videos
    • बिल्ली के नाम की उत्पत्ति वाली बात, Ruby Central drama और Spinel.coop के founders के साथ रिश्तों को देखते हुए, काफ़ी संदिग्ध लगती है
      प्रोजेक्ट का नाम भी कुछ भावनात्मक तरीके से रखा हुआ लगता है
  • यह निस्संदेह बेहद प्रभावशाली है, लेकिन AI agent के बिना maintain करना असंभव-सा लगता है
    spinel_codegen.rb 21 हज़ार lines का है, और कुछ methods में 15 स्तर तक nesting है
    compiler code का सुंदर होना वैसे भी मुश्किल है, लेकिन यह उस मानक से भी इंसानों के लिए maintain करना बहुत कठिन लगता है

    • compiler code को समय हो तो काफ़ी सुंदर बनाया जा सकता है
      compilers में subsystem boundaries साफ़ होती हैं और stages के बीच handoff भी स्पष्ट होता है, इसलिए वे उल्टा सबसे modular बन सकने वाली चीज़ों में आते हैं
      समस्या आम तौर पर यह होती है कि पहले किसी तरह चला दिया जाता है और फिर refactor करने का समय नहीं मिलता, और तब गंदगी बढ़ती ही जाती है
    • spinel_codegen.rb तो लगभग eldritch horror स्तर का है
      Claude के साथ मेरे यहाँ भी हमेशा ऐसा ही spaghetti code निकलता है, तो मुझे लगा मैं ही कुछ ग़लत कर रहा हूँ
      लेकिन जिसे मैं top-tier programmer मानता हूँ, उसके इतने दिलचस्प प्रोजेक्ट में भी जगह-जगह code quality काफ़ी खराब दिखी, तो लगा समस्या सिर्फ मेरे साथ नहीं है
      उदाहरण के लिए infer_comparison_type() सबसे बुरा उदाहरण नहीं है, और पढ़ने में भी असंभव नहीं, लेकिन इसका कहीं ज़्यादा सरल और साफ़ implementation हो सकता था, फिर भी Claude वहाँ तक नहीं पहुँच पाया
      comparison operators को Set में रखकर include? से संभालें तो वह छोटा, तेज़, ज़्यादा readable और maintainable होगा
      लेकिन Claude हमेशा if-return chain की तरफ़ बह जाता है, और कभी-कभी तो लगता है जैसे if-else भी उसे अटपटा लगता है
      मेरे Claude codebase में भी ऐसे patterns भरे पड़े हैं, और अब समझ आया कि यह सिर्फ मेरे यहाँ नहीं है
      दूसरी तरफ़ बाकी files कहीं बेहतर हैं, खासकर lib directory, जो main Ruby repo की ext directory से मेल खाती लगती है और जिसकी quality ठीक है
      API पर MRI Ruby का असर साफ़ दिखता है, और भले implementation काफ़ी अलग हो, Matz ने output को ज़्यादा व्यवस्थित बनाने के लिए शायद original API के कुछ हिस्सों जैसा रखने को कहा होगा
      [1] https://github.com/matz/spinel/blob/98d1179670e4d6486bbd1547...
    • इस चरण पर यह इतना महत्वपूर्ण नहीं लगता कि इंसान इसे हाथ से maintain कर पाएँ या नहीं
      जब तक tests और benchmarks pass हो रहे हैं, मैं फ़िलहाल संतुष्ट हूँ
      लेकिन यह अलग सवाल है कि इतनी बड़ी file AI के लिए भी आसान है या नहीं
      मैं files को 300 lines के भीतर रखने की कोशिश करता हूँ, और मुझे लगता है कि जो code इंसानों के लिए समझना आसान है, वही coding agents के लिए भी आसान होगा
  • सीमाएँ ये बताई गई हैं
    No eval: eval, instance_eval, class_eval
    No metaprogramming: send, method_missing, define_method(dynamic)
    No threads: Thread, Mutex(Fiber supported)
    No encoding: UTF-8/ASCII मानकर चलता है
    No general lambda calculus: [] call के साथ गहरी nested -> x { }
    UTF-8/ASCII वाला हिस्सा मुझे व्यक्तिगत रूप से बहुत बड़ी सीमा नहीं लगता, लेकिन बाकी बातें काफ़ी programs में सचमुच बाधा बनेंगी
    और इन्हें वापस जोड़ने में भी काफ़ी काम लगता है

    • इससे Ruby का काफ़ी magic गायब हो जाता है
  • मैंने Ruby लंबे समय तक इस्तेमाल की है, और सूचीबद्ध सारी सुविधाएँ भी काम में ली हैं; उस नज़रिए से देखें तो विकास के बाद अब मुझे इसी तरह की सरल Ruby चाहिए
    यह ज़्यादा सरल और समझने योग्य है, फिर भी Ruby की खास aesthetic बची रहती है
    अब LLM की वजह से code generation productivity इतनी बढ़ गई है कि पहले जैसी metaprogramming से boilerplate घटाने की ज़रूरत कम हो गई है
    क्योंकि developers द्वारा खुद code लिखने का अनुपात ही घट रहा है

    • अगर आपको बस Ruby aesthetic चाहिए, तो Crystal भी आपको suit कर सकता है
      syntax मिलता-जुलता है और उसमें static type system है, जिससे ज़्यादा efficient compiled code मिलता है
    • eval का न होना तो शायद बेहतर ही है, लेकिन threads और mutexes का भी न होना खलता है
      define_method की अनुपस्थिति उसका उपयोग सोचकर समझ आती है
      लेकिन send और method_missing मौजूदा libraries में आम हैं, और implementation भी compile time पर memory lookup table बनाकर उतनी मुश्किल नहीं लगती
      इसलिए समझ नहीं आता कि इन्हें जानबूझकर छोड़ा गया है या बस अभी तक वहाँ पहुँचे नहीं हैं
      मेरी उम्मीद दूसरी बात है, लेकिन कम-से-कम अभी compatibility के कारण production use मुश्किल लगेगा
    • metaprogramming का असली फ़ायदा कम code लिखना नहीं था
      बल्कि कम code पढ़ना था
  • यह सच में शानदार है, और मैं लंबे समय से Ruby के लिए AOT compiler का इंतज़ार कर रहा था
    बस eval या metaprogramming fallback का न होना अफ़सोस की बात है, हालांकि लगता है कि ऐसा छोटे high-performance subset पर ध्यान केंद्रित करने के लिए किया गया है
    अच्छा होगा अगर इस AOT compiler से बने gem, MRI के साथ अच्छी तरह interact करें
    standard Ruby और gems को package या bundle करने के लिए अभी भी tebako, kompo, ocran की ज़रूरत रहती है, और पहले ruby-packer, traveling ruby, jruby warbler जैसे projects भी थे
    एक और विकल्प आना अच्छी बात है, लेकिन मैं बेहतर developer UX वाले अंतिम निर्णायक समाधान का इंतज़ार कर रहा हूँ

    • सही बात, मुझे भी हाल ही में warbler fork करना पड़ा
      क्योंकि बहुत लंबे समय से उसका update नहीं आया था
  • मुझे समझ नहीं आता no threads क्यों
    Ruby scheduler और नीचे का pthread implementation तो C layer में भी ठीक से काम करना चाहिए, इसलिए लगा शायद zero dependency की कोशिश होगी
    अगर optional extension के रूप में बाद में जोड़ने की योजना नहीं है, या यह सिर्फ अभी तक नहीं हुआ, तो यह चुनाव थोड़ा अजीब लगता है

    • मैंने अभी तक ऐसा कोई संकेत नहीं देखा कि इसे जानबूझकर support न करने का फ़ैसला लिया गया है
      शायद बस अभी तक वहाँ पहुँचे नहीं हैं
      multithreading को ठीक से बनाना वैसे भी बहुत कठिन होता है
  • यह जानकर हैरानी हुई कि इसे एक महीने से थोड़ा ज़्यादा समय में बना लिया गया
    AI के बारे में कुछ भी कहें, कुशल developers के हाथ में यह गति में ज़बरदस्त बढ़ोतरी लाता है

    • पूरी industry agent harness, SOUL.md, permission settings, skills, MCPs, hooks, env वगैरह सब लगाकर शुरू करती है
      और Matz बस gem env|info और find से काम चला लेते हैं, ऐसा लगता है
  • चूँकि इसे Matz ने बनाया है, इसलिए यह जानना दिलचस्प है कि भविष्य में इसके Ruby core का हिस्सा बनने की कितनी वास्तविक संभावना है
    और अगर ऐसा हुआ तो Crystal के लिए यह कितना ख़तरा होगा

    • Crystal में स्पष्ट static type system है, और भाषा स्तर पर ही AOT compilation के लिए optimize किया गया है
      बड़े programs को compile और maintain करने के लिए ये विशेषताएँ लगभग अनिवार्य जैसी हैं
      दूसरी ओर यह सीमित Ruby subset के लिए है, इसलिए ज़्यादातर लोकप्रिय Ruby gems इसमें वैसे के वैसे नहीं चलेंगे
      C compilation की ओर उन्मुख language subset होने के लिहाज़ से यह PreScheme के ज़्यादा करीब लगता है
      अभी के चरण में मुझे नहीं लगता कि दोनों सीधे एक ही क्षेत्र में प्रतिस्पर्धा कर रहे हैं
      पूरी Ruby के लिए लगभग निश्चित रूप से JIT चाहिए होगा
      [1]: https://prescheme.org/
    • दूसरे नज़रिए से देखें तो आख़िरकार LLM उस बिंदु तक पहुँच जाएँगे जहाँ वे हमारी मनचाही किसी भी भाषा में formal specification उगल सकेंगे
      यह कुछ-कुछ Rational Unified Process और Enterprise Architect जैसे tools की वापसी जैसा होगा
      फ़र्क बस इतना होगा कि UML diagrams की जगह markdown files आएँगी
  • यह infrastructure tools के क्षेत्र में उपयोगी हो सकता है
    मान लीजिए bundler Ruby में लिखा है लेकिन statically compiled है, और साथ में RVM जैसे Ruby installation tool की भूमिका भी निभा लेता है
    मौजूदा Ruby buildpack Ruby में लिखा होने के बावजूद bootstrap के लिए bash की ज़रूरत रखता है, जो परेशान करता है और edge cases भी पैदा करता है
    CNB ने उस समस्या से बचने के लिए Rust चुना, और बिना dependencies वाला single binary वितरित कर पाना सचमुच बहुत शक्तिशाली विचार है