- JavaScript सिंटैक्स nested parentheses और callbacks की वजह से आसानी से जटिल हो जाता है, और छोटे UI के लिए भी बहुत-सी libraries खींच लाने वाली bloating पैदा होती है
- WebAssembly ब्राउज़र में दूसरी भाषाएँ चलाने का रास्ता खोलता है, लेकिन Pyodide की तरह JavaScript event loop के साथ asynchronous connection की लागत काफ़ी अधिक होती है
- ब्राउज़र resources और WebAssembly memory सीमित होते हैं, इसलिए JavaScript को replace करने के बजाय उसके साथ मोलभाव करने वाला approach ज़रूरी है
- LispE एक 3.3MB WASM binary में 450 से अधिक functions समेटता है, और strings, computation, matrices, regular expressions को साथ में उपलब्ध कराता है
evaljs और asyncjs के जरिए JavaScript functions और DOM का उपयोग करते हुए, कई external libraries की जगह एक audit की जा सकने वाली single binary से code bloat कम किया जाता है
JavaScript bloating और ब्राउज़र सीमाएँ
- JavaScript सिंटैक्स में parentheses, curly braces और square brackets एक-दूसरे में nested होते हैं और उनके closing order को मिलाना पड़ता है, इसलिए code जल्दी जटिल हो जाता है
forEach callback के अंदर कई objects में values डालने और conditional cache update करने का उदाहरण दिया गया है
newNames.forEach((name, i) => {
allAgentContents[name] = contents[i];
agentModes[name] = modes[i];
if (compiled[i]) agentCompiledCache[name] = compiled[i];
agentViewingCompiled[name] = viewing[i];
});
- जिन processing features को एक basic programming language आम तौर पर शामिल करती है, उनके लिए JavaScript में अक्सर कई libraries डाउनलोड करनी पड़ती हैं
- C या C++ में भी काम करने के लिए
include की ज़रूरत होती है, लेकिन JavaScript libraries में यह समझना अक्सर मुश्किल होता है कि उन्हें किसने implement किया और कौन उनका maintenance कर रहा है
- छोटी-सी window में hello दिखाने के लिए भी ऐसे pages बन जाते हैं मानो “इंटरनेट का आधा हिस्सा” load कर लिया गया हो
- इंटरनेट JavaScript पर निर्भर है, और TypeScript से उसे छिपा भी दिया जाए तो भी ब्राउज़र में page खुलते समय वही gatekeeper बना रहता है
- कभी यह सपना था कि ब्राउज़र अंतिम operating system बन जाएगा और Windows या Mac OS को अनावश्यक कर देगा, और उस सपने को लागू करने के लिए JavaScript को चुना गया
WebAssembly और JavaScript का संबंध
- WebAssembly अपनी खुद की machine language वाली virtual machine के क़रीब है, इसलिए यह ब्राउज़र के अंदर अलग ढंग से coding करने की संभावना खोलता है
- Pyodide ब्राउज़र में Python चलाने की प्रभावशाली engineering उपलब्धि है, लेकिन यह JavaScript domain के भीतर काम करने की लागत भी दिखाता है
- Python का
asyncio और JavaScript event loop, इन दो asynchronous दुनियाओं को एक-दूसरे से बात करनी पड़ती है
- इन दोनों दुनियाओं के बीच का पुल नाज़ुक है, और हर
await के बारे में याद रखना पड़ता है कि वह किस दुनिया से जुड़ा है
- ब्राउज़र resources सीमित होते हैं, इसलिए computer science के शुरुआती दौर की तरह हर command और structure को bit level पर देखने वाली सोच की ज़रूरत है
- 1981 में ऐसे computer पर programming शुरू करने का मानदंड दिया गया है जिसमें ठीक 15772 bytes ही बचे थे
- आधुनिक ब्राउज़र memory पहली computer जितनी सीमित नहीं है, लेकिन WebAssembly सामान्य programs की तरह memory पर स्वतंत्र ownership नहीं रखता और सीमित तरीके से पहले अनुमति लेनी पड़ती है
- मुख्य रुख JavaScript से लड़ना नहीं, बल्कि उसके साथ मोलभाव करना है
LispE द्वारा पेश किया गया विकल्प
- LispE एक single binary के भीतर 450 से अधिक functions उपलब्ध कराता है
- WASM binary का आकार 3.3 MB है
- strings, computation, matrices और regular expressions processing एक ही जगह बंधे हुए हैं
- WASM binary binaries/wasm में उपलब्ध है
- यह छोटा interpreter है, लेकिन return value के रूप में strings,
Float64Array, integers, real numbers और string arrays संभाल सकता है
- LispE, Lisp-आधारित होने के कारण, AST को जीवित संरचना की तरह बनाए रखता है
- अगर Lisp syntax उपयुक्त न लगे, तो Python या Basic से अलग पहचानना मुश्किल ऐसे language के लिए transpiled syntax इस्तेमाल किया जा सकता है
- grammar को बदलकर मनचाहे style की language बनाई जा सकती है
- यह Greek में भी संभव है, और पहले से Greek example मौजूद है
- LispE, JavaScript से लड़ने के बजाय JavaScript functions और DOM features का उपयोग करके सहयोग करता है
JavaScript calling: evaljs और asyncjs
- LispE के भीतर JavaScript code चलाने के लिए
evaljs और asyncjs का उपयोग किया जा सकता है
evaljs JavaScript code चलाकर value प्राप्त करता है
asyncjs page में defined user JavaScript functions और asynchronous callbacks को जोड़ता है
(setq a (evaljs "10 + 20 + 30")) ; execute some JS code
; call_llm is a user-defined JS function in the page
(asyncjs `call_llm("Implement a piece of code in Python to sort strings");` 'mycallback)
(defun mycallback(theresult) ...)
asyncjs इस Promise की तरह काम करता है कि काम पूरा होने पर वापस आएगा
code bloat कम करना
- 1995 के Wirth उद्धरण से यह निष्कर्ष निकलता है कि तेज़ computers और बड़े models समस्याओं का समाधान नहीं करते, और code को पतला बनाए रखना चाहिए
- LispE ब्राउज़र के सामने उजागर होने वाले 450 functions को एक single audit की जा सकने वाली binary के रूप में देता है
- हर feature को अलग से implement करने के लिए
mathjs जैसी numerical computation library, lodash जैसी collection library, voca जैसी string manipulation library, और simple-statistics जैसी statistical distribution library load करनी पड़ सकती है
- यह तरीका अलग-अलग authors, bugs और maintenance schedules वाले सैकड़ों MB code तक बढ़ सकता है
- LispE एक ही maintained codebase में ये features देता है, और open source होने के कारण पूरे code का audit किया जा सकता है
- यह माना गया है कि Garbage Collector सबसे बुरे समय पर code performance को ध्वस्त नहीं करता
- यह JavaScript के साथ simple API calls के जरिए पारदर्शी ढंग से communicate करता है, और predefined structures return कर सकता है
// floats here is a Float64Array
const floats = callEvalLispEToFloats(0, `(normal_distribution 100)`);
2 टिप्पणियां
लेख थोड़ा अचानक-सा लगा, इसलिए मैंने source पर शक किया था, लेकिन वो Naver निकला, haha.
लेकिन जैसा उम्मीद था, प्रतिक्रिया अच्छी नहीं है... सच कहूँ तो JavaScript को इतना बढ़ा-चढ़ाकर 3.3MB का WASM तक चढ़ाकर Lisp इस्तेमाल करने की बात करना ऐसा over-engineering है जिसे आसानी से समझना मुश्किल है, lol.
Claudius नाम के project के एक developer ने इस बारे में comment छोड़ा कि वो Naver Labs Europe में काम करते हैं और Naver ने इसे open source project के तौर पर approve किया, इसलिए यह पोस्ट हुआ।
लगता है Naver से इसका बहुत बड़ा संबंध नहीं है, बस शायद ये लोग सच में Lisp से बहुत प्यार करते हैं...
Lobste.rs की राय
JavaScript को कम bloated बनाने की बात करते हुए एक अपारदर्शी 3.3MB WASM का ढेला जोड़ना और फिर कहना कि app को Lisp में लिखो — कुछ अजीब लगता है
सिर्फ शुद्ध JavaScript और 0 अतिरिक्त dependencies के साथ भी उस size के दसवें हिस्से तक पहुंचे बिना काफी कुछ बनाया जा सकता है
मैं इस उपयोग-तरीके से सहमत नहीं हूं, लेकिन यह एक दिलचस्प Lisp passion project है जिसमें आजकल कम दिखने वाली अजीब-सी खासियत है, और अच्छा लगा कि पूरा documentation इंसानों के हाथ से लिखा हुआ महसूस होता है, इसलिए उसकी भाषा अलग लगती है
standard library में नया जोड़ा जा सके, ऐसी चीज़ों के लिए हमेशा proposals खुले रहते हैं
हाल की additions में set union/intersection,
sum,base64वगैरह शामिल हैंलेकिन calculus functions की मांग मैंने लगभग कभी नहीं सुनी, और strings के मामले में लगातार जो requests आती हैं वे
.reverseया.titleCaseजैसी हैं.reverseके toy problems से बाहर बहुत compelling use cases नहीं हैं, और.titleCaseसंभव तो है, लेकिन इसके लिए i18n data चाहिए, इसलिए चर्चा जारी हैऔर इनमें से कोई भी इस library में नहीं है
उन्हें लगता है कि proposal देने का कोई फायदा नहीं, क्योंकि असली inclusion में 3 साल लग जाएंगे, और
utils/folder भले अच्छा न हो, पर अभी बनाया तो जा सकता हैमेरी दलील JavaScript में functions की कमी से ज्यादा deployment model के बारे में है
चाहे standard library पूरी तरह भरी हुई हो, एक औसत app फिर भी megabytes में transitive npm dependencies लेकर ship होता है
LispE-as-WASM 3.3MB का है, इसमें लगभग 450 documented functions हैं, एक C++ core है, और GitHub पर open source है; यह एक प्रयोग है कि audit किया जा सकने वाला runtime कैसा दिख सकता है
मैंने वास्तव में इसके ऊपर एक agent harness बनाया है, और browser के अंदर ही LispE rules को तुरंत चला रहा हूं
JavaScript event loop मुझे बहुत पसंद है
जब कोई syntax को bloated कहता है तो मैं सावधान हो जाता हूं
minimal syntax, visual distinction के लिए अलग-अलग characters इस्तेमाल करने वाली syntax की तुलना में, पढ़ने में कहीं ज्यादा कठिन हो सकती है
LispE इसके विकल्प के रूप में यह पेश करता है:
... !?
https://github.com/naver/lispe/wiki/5.3-A-la-APL
इस project में जाने का entry point थोड़ा अजीब है, और https://github.com/naver/lispe/wiki/1.-Introduction वाला पेज बेहतर लगता है
यह WASM को target करने वाला भी एक native Lisp project है, और programming language nerds को पसंद आने वाली कुछ मजेदार बातें इसमें हैं
मेरी पहली impression यह थी कि यह काफी forced JavaScript examples का मामला है
JavaScript से नफरत का बड़ा हिस्सा शायद शुरुआती browser incompatibility, तकलीफदेह DOM APIs, और syntax traps से आया था, और ये चीज़ें आजकल की मेरी रोजमर्रा की जिंदगी में लगभग असर नहीं डालतीं
modern JavaScript, खासकर TypeScript और ठीक-ठाक lint rules के साथ, एक language के रूप में काफी ठीक है
अब भी CJS बनाम ESM, supply-chain risk, ecosystem churn जैसी समस्याएं हैं, लेकिन उनमें से ज्यादातर language के बाहर की हैं
parentheses का balance मिलाना इतना झंझट भरा था कि लोगों ने editor extensions तक बना दिए — क्या वही experience शानदार कहा जा रहा है?
अगर आपको इस तरह की programming, यानी low syntax density और functional style, चाहिए तो दिशा पलटकर concatenative language की ओर जाना बेहतर होगा
समझ नहीं आता कि Lisp interpreter compile होने के बाद 3.3MB तक कैसे पहुंच जाता है
क्या इसे ही कम bloated कहना है?
फिर भी, इस्तेमाल न होने वाले code समेत बड़ी standard library को साथ में ship करना bloating कम करने से काफी दूर की बात है — इस पर मैं सहमत हूं
सदमा! डर!
closing parentheses को सही क्रम में बंद करना पड़ेगा, क्या आश्चर्य है
JavaScript जैसी languages की verbosity से चिढ़ने वाले Lisp प्रशंसक भी APL-family languages के सामने अक्सर पलट जाते हैं, और फिर सबसे छोटेपन के बजाय clarity और readability के ज्यादा महत्वपूर्ण होने पर बहस करने लगते हैं
LispE के लेखक को APL primitive operations से कुछ लगाव दिखता है, लेकिन इतनी concise notation वाली languages देखने के बाद भी Conway’s Life को APL, J, K, यहां तक कि Q versions से लंबा, ज्यादा ढीला और गहरे nested s-expressions वाले रूप में पसंद करने की वजह समझना मुश्किल है