3 पॉइंट द्वारा GN⁺ 2024-10-25 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Pretty C, C-compatible नई scripting language है, जो C programs में dynamic typing, generic iteration, resource tracking जैसी convenience features जोड़ती है
  • इसे इस्तेमाल करने का तरीका pretty.h को include करने वाली header-only library के रूप में है, और इसे existing C files व C libraries के साथ इस्तेमाल किया जा सकता है
  • इसमें string, any, nil जैसे aliases, var/let type inference, print/println generic output, equal generic comparison, और पढ़ने में आसान ternary-expression macros शामिल हैं
  • iteration और memory work घटाने के लिए यह foreach, forthese, fortimes, forrange, new, vector, delete, with, lambda, try/catch जैसी macro-based syntax देता है
  • कुछ features के लिए GCC, Clang, C23+, C11+ जैसी शर्तें हैं, और with से bound variables void * होते हैं, इसलिए इस्तेमाल से पहले type conversion की जरूरत पड़ सकती है

Pretty C का लक्ष्य और इस्तेमाल का तरीका

  • Pretty C, C-compatible scripting language है और C programs में dynamic typing, generic iteration, resource tracking तथा कई syntax convenience features जोड़ती है
  • existing C और C libraries के साथ backward compatibility बनाए रखती है
  • Lua, Python, JavaScript, Lisp से प्रेरित है
  • installation के लिए repository clone की जा सकती है या सिर्फ pretty.h file copy करके इस्तेमाल किया जा सकता है
    • किसी भी C file में #include "pretty.h" से include किया जा सकता है
    • include path में Pretty C path specify करके भी इस्तेमाल किया जा सकता है

Basic included headers और simple macros

  • Pretty C standard headers include करता है ताकि अक्सर इस्तेमाल होने वाले types और operator replacements तुरंत इस्तेमाल किए जा सकें
    • stdbool.h: true, false, bool
    • stdint.h: uint64_t जैसे fixed-width integer types
    • iso646.h: && की जगह and, || की जगह or जैसे alternative operators
  • अक्सर define किए जाने वाले simple macros भी देता है
    • max, min: दो numbers का maximum और minimum
    • len: array length
    • default: fallback value देता है
    • limit: value range limit करता है
    • between: जांचता है कि number range के अंदर है या नहीं
    • divisible: जांचता है कि किसी दूसरे number से पूरा divide होता है या नहीं

Types और aliases

  • Pretty C, C types के लिए छोटे type aliases देता है
    • string यानी char*
    • byte यानी char
    • bytes यानी char*
    • any यानी void*
    • integer short forms के रूप में uchar, ushort, uint, ulong देता है
  • Lua और Lisp से प्रभावित syntax aliases भी शामिल हैं
    • eq, is: ==
    • bitnot, bitxor: bit-operation aliases
    • success, fail, failure: success == 0 pattern के aliases
    • below, above, upto, downto: comparison operators
    • even, odd, positive, negative, zero, empty: numbers और data predicates
    • nil: NULL
    • until: negative while
    • elif: else if
    • ifnt, elifnt: if(!...) style expressions
    • repeat: Lua-style do alias
    • done, finish, pass: break, continue aliases
    • always, forever, loop, indefinitely: infinite-loop expressions
    • never, comment: ऐसे expressions जिनसे code execute नहीं होता, फिर भी compiler उसे analyze कर सकता है

Type inference, output, comparison, ternary expressions

  • Type inference GCC, Clang या C23+ में इस्तेमाल की जा सकती है
    • उदाहरण के तौर पर var t = time(0);, let lt = localtime(&t);, local at = asctime(lt); जैसी forms देता है
  • Generic output C11+ में इस्तेमाल किया जा सकता है
    • print दिए गए value को output करता है
    • println output के बाद newline जोड़ता है
  • Generic equality comparison भी C11+ feature के रूप में दिया गया है
    • equal("NA", line) जैसी string comparison
    • equal(0.3, 0.2 + 0.1) जैसा comparison example शामिल है
  • Ternary operator को text-based macros से ज्यादा readable बनाया जा सकता है
    • when readability के लिए empty string में expand होता है
    • unless not में expand होकर when के negative form की तरह काम करता है
    • then यानी ?
    • other और otherwise यानी :
    • only तब इस्तेमाल होता है जब otherwise clause की जरूरत नहीं होती
    • otherwhen अगली condition जोड़ने के लिए इस्तेमाल होता है

Iteration macros

  • Pretty C अक्सर इस्तेमाल होने वाले for loop patterns को macros से abstract करता है
  • foreach (var, type, length, ...)
    • array या memory region पर iterate करता है
    • हर iteration में var उस array element का pointer बनता है
    • pointer होने के कारण जरूरत पड़ने पर element को in-place modify किया जा सकता है
  • forthese (var, type, ...)
    • दिए गए variadic arguments पर iterate करता है और हर value को type के var से bind करता है
  • fortimes (var, times)
    • 0 से positive count तक repeat करने वाले common pattern को छोटा करता है
  • forrange (var, init, target)
    • init से target तक numeric range पर iterate करता है
    • init और target कोई भी signed या unsigned integer हो सकते हैं
    • अगर init, target से बड़ा है तो iteration step घटता है
  • forrangeby (var, type, init, target, by)
    • specified type वाले var को init से target तक by interval में iterate करता है

Allocation और block utilities

  • Allocation macros C++ से प्रभावित रूप में common memory allocation patterns को simplify करते हैं
    • new (type, ...): C++ new जैसी form में structs आदि बनाता है
    • vector (length, type, ...): specified length और type की array allocate करने और initial contents डालने के pattern को simplify करता है
    • delete (...): free जैसा ही है, लेकिन C++-style नाम पसंद हो तो इस्तेमाल किया जा सकता है
  • Block utilities local binding, deferred execution और block-level work के लिए macros देते हैं
    • lambda (ret, name, ...): GCC, Clang या C++ में nested functions, lambdas, closures जैसी forms को C में इस्तेमाल करने देता है
    • with (var, close, ...): resource release function close पहले से देकर dynamically allocated objects या file handles के लिए उपयोगी है
      • कमी यह है कि bound var void * होता है, इसलिए इस्तेमाल से पहले उसे desired type में convert करना पड़ सकता है
    • defer: हटा दिया गया है, और नए उपलब्ध defer का इस्तेमाल करने के लिए guide करता है
    • try और catch: C में error handling को ज्यादा elaborate रूप में लिखने देता है
    • NOERR, NOERROR: error switch-case convenience के लिए दिए गए हैं

Contribution का तरीका

  • function जोड़ते समय Linux Kernel Style Guide follow करने का अनुरोध है
    • commit से पहले make indent चलाने की सिफारिश है
  • A’s Commit Message Guide follow करना preferred है, लेकिन required नहीं

1 टिप्पणियां

 
GN⁺ 2024-10-25
Hacker News की राय
  • C के अंदर domain-specific language बनाने की परंपरा काफी पुरानी है
    Stephen Bourne shell को ALGOL की तरह लिखना चाहते थे, इसलिए उन्होंने C preprocessor को लगातार इतना पीटा कि वह आखिरकार उनकी पसंदीदा भाषा जैसा दिखने लगा
    https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh...

    • उससे लिखा गया उदाहरण यहां है
      https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh...
    • जितना सोचा था, उससे आधा भी डरावना नहीं है
    • यह एक शानदार Unix legend है। कहा जाता है कि यह Obfuscated C Code Contest की प्रेरणा था
      https://www.ioccc.org/
  • सोच रहा हूं कि कोई समझा सकता है क्या कि यह मजाक है, या लेखक सच में उलझा हुआ है
    कुछ भी समझ में नहीं आता। यह “scripting” भी नहीं है, “strong typing” लाने की बात करता है लेकिन types के साथ कुछ नहीं करता, और Lua तथा Lisp से प्रेरित बताए गए operator aliases असल में उन दोनों भाषाओं में कहीं नहीं हैं। फिर भी यह साफ-साफ parody जैसा भी नहीं दिखता, इसलिए वाकई उलझन होती है

    • लगता है यह सच में serious है। क्योंकि वह कहता है, “Lua, Python, JavaScript, Ruby और दर्जनों दूसरी भाषाओं को हटा दो। Pretty C ultimate scripting language है, बिजली जैसी तेज और strong typing के साथ!!”
    • मुझे बिल्कुल नहीं लगता कि लेखक confused है। हालांकि confused होना अपने-आप में ठीक है
  • यह खुद को scripting language कहता है, लेकिन program अब भी compile करना पड़ता है। हूट करने लायक है
    CINT(https://root.cern.ch/root/html534/guides/users-guide/CINT.ht...) जोड़ दें तो तुरंत execution और REPL भी संभव है

    • अगर इस repository का मकसद दर्द देना है, तो file में shebang जोड़कर उसे executable क्यों न बना दें [0]
      पहले मैंने एक blog post देखी थी जिसमें ./foo कैसे काम करता है और ELF file कैसे execute होती है, यह विस्तार से बताया गया था। उसी तरीके से .c programs को register करके compile के बाद run कराया जा सकता है
      [0] https://gist.github.com/jdarpinian/1952a58b823222627cc1a8b83...
    • बेहतर होगा tcc ही इस्तेमाल करें [0]। उस राक्षस से कहीं ज्यादा हल्का है, और C++ नहीं बल्कि C है
      [0] https://bellard.org/tcc/tcc-doc.html
    • CERN अब cling इस्तेमाल करता है (https://github.com/root-project/cling)
    • किसने तय किया कि scripting language compile नहीं हो सकती? और Clang-REPL भी इसे REPL-friendly बनाने का एक और तरीका है
  • “C developers को diabetic heart attack दिला देने जितनी syntactic sugar देता है।”
    यह line मुझे बहुत पसंद आई

  • CNoEvil[0] और ogw[1] में जोड़ने लायक कुछ चीजें दिख रही हैं। लगता है हर कुछ महीनों में जब यह project फिर ऊपर आता है, हमेशा और चीजें मिल जाती हैं
    [0] https://git.sr.ht/~shakna/cnoevil3/
    [1] https://git.sr.ht/~shakna/ogw

    • “ढेर सारे खराब ideas लेकर उन्हें एक घिनौने monster में मसलकर भर देता है।”
      यह ऐसा वाक्य है जिससे सचमुच दिल की गहराई से प्यार हो जाता है
  • यह Python 2 जैसी ही गलती कर रहा है। strings और bytes एक ही type नहीं हैं, और उन्हें ऐसा treat भी नहीं करना चाहिए

    • shell text, यानी argv में मौजूद values या child process output का type क्या माना जाना चाहिए?
      उसमें कोई भी random garbage value आ सकती है, इसलिए वह valid UTF-8 string नहीं है, लेकिन awk और grep जैसे tools हर जगह इस्तेमाल होते हैं
      strings और bytes को एक ही general type माना जा सकता है, बस कभी-कभी valid UTF-8 bytes को internally अलग type देना उपयोगी होता है। Rust इस हिस्से को OsString और String से काफी अच्छी तरह handle करता है
    • यह project pretty.c है और कहता है कि इसका इरादा “C और सभी libraries के साथ backward compatible” रहना है, तो C की multibyte strings बनाए रखने से ज्यादा logical विकल्प क्या होगा?
      https://en.cppreference.com/w/c/string/multibyte
    • सहमत नहीं हूं। यह सिद्धांत इन सभी assumptions पर टिका है: string data सही तरह encode होता है, string encoding सिर्फ एक होती है (आमतौर पर UTF-8), string data बनते समय validate होना चाहिए, logical codepoints को काटना कभी allow नहीं होना चाहिए, “invalid” bytes पर string operations नहीं करने चाहिए, सही encoding ही validation की शुरुआत और अंत है
      इनमें से कोई भी बात हमेशा सच नहीं है। validated byte sequence को ऐसे type में wrap करना उपयोगी है जिसे केवल validation के जरिए बनाया जा सके, लेकिन ऐसा करने के बाद Utf8String और EmailAddress मूल रूप से एक ही category के हो जाते हैं। type system में सिर्फ encoding को special treatment देने की कोई वजह नहीं है
    • यह इस पर निर्भर करता है कि आप “string” को कैसे define करते हैं
      अगर उसका मतलब “इंसान द्वारा पढ़ा जा सकने वाला text” है, तो मैं सहमत हूं कि string किसी arbitrary byte array के समान नहीं है। लेकिन कई languages इस definition को enforce नहीं करतीं
  • पहले एक C++ codebase याद आया जिसकी मुझे जाँच करनी पड़ी थी। पूरा ऐसा बना था जैसे Java में लिखा गया हो: हर चीज़ में camelCase, हर class variable के लिए getter/setter, और जगह-जगह interfaces थे

    • आपने अभी असली चीज़ देखी ही नहीं। Unix Seventh Edition का Bourne shell source देखिए
      https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd...
      यकीन करना मुश्किल है कि यह ALGOL नहीं है
    • camelCase, getter/setter और interfaces कई मामलों में guidelines से बहुत अलग नहीं हैं। उदाहरण के लिए Windows code ऐसा है, हालांकि ज़ाहिर है हर variable तक नहीं। Java के design का बड़ा हिस्सा भी C++ से copy किया गया था
    • मैंने भी ऐसा ही codebase देखा है, जिसे शायद उन लोगों ने लिखा था जिन्होंने बहुत लंबे समय तक Java इस्तेमाल किया था। यहाँ तक कि एक अपनी String class भी थी, जो बस std::string को wrap करती थी, लेकिन उस पर Java-style methods लगाए गए थे
    • लगता है MSVC इस्तेमाल न करना अच्छी बात रही
      https://learn.microsoft.com/en-us/cpp/cpp/property-cpp?view=...
    • मैंने भी ऐसा झेला है, और उसके ऊपर Java की तरह strings को f(String *) के रूप में pass किया जाता था, इसलिए C++ code f(new String("Hello") जैसा था
  • अगर यह दिलचस्प लग रहा है, तो आपको libcello.h भी पसंद आ सकता है
    https://www.libcello.org

    • सही है, यह प्रेरणाओं में से एक है
  • type names अच्छे हैं, और min जैसे built-in function macros का चुनाव भी बिल्कुल सही है। Len भी पसंद आया
    नाम वाले boolean operators शायद थोड़ा ज़्यादा हो सकते हैं, लेकिन आज़माने लायक हैं, और ternary operator वैसे भी पढ़ने में मुश्किल होता है, इसलिए उसमें सुधार की काफी गुंजाइश है। सभी loop definitions को लेकर मैं पूरी तरह convinced नहीं हूँ, लेकिन कुछ समझ में आते हैं। resource tracking प्रभावशाली है, और for... वाला रूप थोड़ा भद्दा है, इसलिए शायद उसे कोई और नाम दिया जा सकता है
    कुल मिलाकर यह काफी मजबूत प्रयास है। design को मैं लगभग 8/10 देना चाहूँगा। C macros से sketch किया गया तरीका सचमुच elegant है और असल में अच्छे code जैसा दिखता है। मैं खुद इस्तेमाल करूँगा या नहीं, पता नहीं। यह एक नई language है और मुझे पहले से C पसंद है। फिर भी implementation बहुत साफ़ है, इसलिए यह लोगों को C सीखने और language design पर सोचने में मदद कर सकता है

    • सब कुछ इस्तेमाल करना ज़रूरी नहीं है। मेरे projects आम तौर पर boolean, len(), max/min, और कुछ operator macros ही इस्तेमाल करते हैं। क्योंकि अभी बाकी स्वादिष्ट features की ज़्यादा ज़रूरत नहीं पड़ी। इसलिए कम से कम कुछ operator macros आज़माकर देखना अच्छा रहेगा
  • if(!...) के लिए ifnt की बात हो, तो unless मुझे ifnt से ज़्यादा readable लगता है

    • नामों पर एक और बहस की चीज़: infinite for(;;) loop को always कहना भी है
      दूसरी languages में मैंने loop देखा है। लेकिन Qt इसे forever कहता है, और यह सच में सुंदर है। बहुत Qt जैसा भी है
    • उलटा, ifnt को ज़ोर से बोलने पर मज़ा आता है
    • सही। लेकिन unless को ternary condition के लिए बचाकर रखा था। क्योंकि वह वहाँ किसी भी तरह ज़्यादा उपयोगी है
      अरे, ठहरो, यह तो John Tromp हैं। BLC बनाने वाले! मैं fan हूँ