Elixir v1.20: अब एक gradual type language
(elixir-lang.org)- type inference और gradual type checking अब सभी Elixir प्रोग्राम्स पर लागू होते हैं, जिससे type annotations के बिना भी dead code और runtime पर निश्चित रूप से fail होने वाले verified bugs खोजे जा सकते हैं
dynamic()type, “anything allowed” वालेany()से अलग, runtime पर संभव type range को track करता है और केवल तब violation report करता है जब वह allowed type से बिल्कुल भी overlap न करेdynamic(integer() or binary())value, numeric operations या string functions जैसी calls में जहाँ कुछ संभावनाएँ overlap करती हैं, violation नहीं देती, लेकिनMap.fetch!जैसी calls में जो केवल map लेती हैं, violation देती हैdynamic()उपयोग के तरीके के अनुसार narrow होता है, औरdata.a + data.bजैसे code मेंdataको%{..., a: number(), b: number()}रूप वाले map के रूप में refine करता है- guard में union, intersection, negation infer किए जाते हैं, ताकि
is_list,is_integer,is_map_key,not is_map_key,tuple_sizeजैसी conditions को type information के रूप में इस्तेमाल किया जा सके caseऔर conditionals, पिछले clause की जानकारी को अगले clause में reflect करते हैं, जिससे पहलेnilhandle करने के बाद बचे हुए value कोbinary()तक narrow करने जैसी type checking की जा सके- standard library के tuple और map से जुड़ी कई functions में types जोड़े गए हैं, जिससे existing codebases में redundant clauses और dead code खोजने में मदद मिलती है
- “If T: Benchmark for Type Narrowing” में 13 categories में से 12 pass करके यह दिखाया गया कि सामान्य Elixir code में precise type information recover की जा सकती है
- v1.20 ने multi-core environments में applications के लिए compile time को फिर बेहतर किया है, और synthetic benchmarks में Elixir build tool ने BEAM languages में सबसे तेज़ results दिखाए
- नया compiler option
:module_definitionmodule definition execution method को default:compiledया:interpretedके रूप में चुनने देता है, और इसेmix.exsकेelixirc_options: [module_definition: :interpreted]से activate किया जा सकता है :module_definitionoption, disk पर लिखी जाने वाली.beamfiles को प्रभावित नहीं करता और केवलdefmoduleके अंदर execution method बदलता है, जिससे बड़े projects के compile time सुधारने में मदद मिल सकती है- set-theoretic types का उपयोग करने वाले नए type signatures पर v1.20 के type system performance, recursive types, parameterized types, और map key-value traversal research पूरी होने के बाद typed struct definitions के साथ चर्चा की जाएगी
1 टिप्पणियां
Hacker News की राय
यह शायद मेरा निजी अनुभव हो, लेकिन जो भाषाएँ शुरू से typed नहीं थीं, वे वास्तविक static typed languages जितना अच्छा काम नहीं करतीं
मैं लगभग 10 साल से पेशेवर Elixir developer के रूप में काम कर रहा हूँ, और types आने का लंबे समय से इंतज़ार कर रहा था। इस बार उसकी शुरुआत सच में आ गई, यह देखकर बहुत खुशी है
लेकिन मैं जानना चाहूँगा कि v1.20 में जो आया है, वह spec-less Dialyzer की तुलना में कैसा है। Dialyzer के success typing approach को मैं इस तरह समझता था कि यह “अगर arguments के कोई ऐसे combinations हों जो fail कर सकते हैं तो warning दो” की बजाय “अगर arguments का एक भी combination काम कर जाता है तो warning मत दो” के ज़्यादा करीब है। मुझे लगा था Elixir भी यहाँ कुछ वैसा ही कर रहा है, और Dialyzer मुझे ज़्यादा उपयोगी नहीं लगा था
Elixir के gradual type system पर कुछ पोस्ट्स HN पर देखी हैं, लेकिन मैंने उन्हें विस्तार से follow नहीं किया। मैं जानना चाहता हूँ कि क्या यह gradual type system, type-less code की तुलना में, किसी प्रोग्राम की asymptotic complexity बदल सकता है
जहाँ तक मुझे पता है, ज़्यादातर gradual type systems, जैसे Racket, प्रोग्राम को asymptotically और धीमा बना सकते हैं, हालांकि कुछ exceptions भी हैं [1]
[1] https://doi.org/10.1145/3314221.3314627
ज़्यादातर gradual type systems typed और untyped code की boundary पर, जब values पार होती हैं, तब enforcement डालते हैं। उदाहरण के लिए, list के सभी elements की जाँच करना, या values को type proxies में wrap करना। लेकिन Elixir टीम ने ऐसे runtime checks के बिना soundness पाने के लिए strong arrows का परिणाम प्रकाशित किया, और compiler जो bytecode बनाता है वह अर्थ की दृष्टि से untyped code के समान ही है
विडंबना यह है कि आलोचक कहते थे कि types की ज़रूरत है, और Elixir fans कहते थे कि types की ज़रूरत नहीं, Elixir किसी तरह जादुई है, इसलिए type-related bugs आते ही नहीं। अब जब types जोड़े गए हैं, तो वही bugs पकड़ रहे हैं। क्या पहले यह नहीं कहा जाता था कि bug prevention के लिए इनकी ज़रूरत नहीं? फिर भी यह एक अच्छा बदलाव है। मैंने पहले Elixir काफ़ी इस्तेमाल किया है और मुझे वह पसंद भी था, लेकिन types की अनुपस्थिति से सहमत होना मुश्किल था
https://en.wiktionary.org/wiki/Goomba_fallacy
मैं उस दृष्टिकोण से सहमत नहीं हूँ, लेकिन यह “$LANGUAGE जादुई है” कहने से कहीं अधिक defensible दावा है
set-theoretic type theory के विकसित होने से पहले यह रुख शायद सही भी रहा हो
फिर अंत में static types जोड़ ही दिए जाते हैं। Python, JavaScript, Ruby में ऐसा हुआ, और भी भाषाओं में हुआ होगा
यह बहुत अच्छा लगता है कि Elixir को update करने पर कई projects में breaking changes नहीं आते, और compiler मुफ्त में bugs भी पकड़ देता है। अब तो इसकी आदत-सी पड़ गई है
यह देखकर सच में खुशी हुई। अब यह “बेहतरीन भाषा” के स्तर के और करीब पहुँच रही है, और मेरे लिए Elixir पहला दावेदार है
अगर कोई दूसरी भाषा है जो पहले से ही इस्तेमाल में आसान है और फिर भी शानदार features को लगातार stable और safe तरीके से जोड़ती रहती है, तो बताइएगा। मैं Go में दक्ष हो रहा था, फिर advanced C# सीखने की तरफ मुड़ गया, क्योंकि Go में अच्छे features जुड़ना जैसे रुक-सा गया था
पिछले एक महीने में मैंने Elixir exercism.io track किया https://exercism.org/tracks/elixir
यह सच में शानदार है
आह, फिर से शुरू हो गया। लगता है अगले 1 साल तक फिर Elixir सीखना पड़ेगा
Elixir की हर चीज़ अच्छी लगती है, लेकिन किसी भी दूसरी language से ज़्यादा Elixir मुझे खुद पर शक करने पर मजबूर करती है। लगता है मेरा दिमाग functional के लिए बना ही नहीं है, लेकिन इस बदलाव की वजह से इसे फिर से आज़माने का मन हो रहा है
अफ़सोस की बात यह है कि ecosystem को beginner-friendly कहना मुश्किल है, और सवालों के जवाब देते समय अक्सर यह मान लिया जाता है कि आपको language पहले से काफ़ी आती है
शीर्षक पर मत जाइए। किताब का पहला आधा हिस्सा बस Elixir ही है
पिछले 8 सालों में जब-जब मुझे Elixir में फिर से ढलना पड़ा, मैंने यही किताब उठाई, और हर बार यह काम आई। इसे कभी पूरा नहीं पढ़ा
इस तरह की tutorial-project शैली की programming किताब अच्छी है या नहीं, इसे परखने का एक तरीका यह है कि अगर आप इसे कई बार शुरू करें लेकिन अंत तक न भी पहुँचें, तब भी क्या बीच तक आते-आते आपके पास अपने काम पर लौटने लायक tools आ जाते हैं
लेकिन मुझे लगता है कि यह दिमाग के अनुकूल न होने से ज़्यादा इस बात का असर है कि imperative languages में आपका अनुभव जिस स्तर पर है, pure functional style में आपको फिर से beginner बनकर शुरू करना पड़ता है
यह धीरे-धीरे बेहतर होगा। functional programming में सहज होने का मोड़ मेरे लिए तब आया, जब मुझे एहसास हुआ कि मुझे Bash की अच्छी spacing वाली “one-liner” जैसी चीज़ों को जोड़ना कितना पसंद है। डेटा किसी रूप में शुरू होता है, आप उसे किसी command में dump करते हैं, फिर सोचते हैं कि उसे चाही हुई शक्ल के थोड़ा और क़रीब लाने के लिए अगली command में pipe करना है, फिर दोबारा देखते हैं। ऐसा करते-करते आख़िर में आम तौर पर आपके पास बिना बदले जाने वाले data transformations की एक श्रृंखला बचती है
shell में यह सहज लगने का एक कारण यह भी है कि आप रोज़ file system में घूमते हुए commands की vocabulary बनाते रहते हैं। Unix-जैसे environment में आपकी परिचित “functions” की library सालों में काफ़ी बड़ी हो चुकी होती है। pure functional programming environment में भी यही करना होता है, बस vocabulary सीखने में थोड़ी ज़्यादा मेहनत लगती है। अक्सर इस्तेमाल होने वाले “commands” grep, cat, sort की जगह map, fold, zip जैसी functions बन जाती हैं
लेकिन मूल बात सचमुच वही है, और pipeline बनाने का आकर्षण दोनों तरफ़ एक जैसा लागू होता है। आप चीज़ों को टुकड़ों में बना सकते हैं, और हर puzzle में पिछला चरण भूलकर बस यह सोच सकते हैं कि सामने के data को अगली बार कैसे transform करना है। यही कम संदर्भ-भार ताज़गीभरा और सुकून देने वाला है
ज़रूर कोशिश करें और उम्मीद है कि आपको इसमें मज़ा आएगा। जब आप किसी चीज़ में अभी अच्छे न होने की स्थिति का आनंद लेना सीख लेते हैं, तभी आप सच में उसमें अच्छे होने लगते हैं
बेशक मैंने इसे बस कुछ दोपहरों तक ही आज़माया है, लेकिन अगर मुझे अपने दिमाग को फिर से functional languages के लिए प्रशिक्षित करना हो, तो शायद परिचय की वजह से मैं Gleam चुनूँगा
कभी-कभी पोस्ट अस्पष्ट होने की वजह से ध्यान नहीं खींच पाती, या उनमें “मेरा homework कर दो” वाली गंध होती है, इसलिए उन्हें नज़रअंदाज़ कर दिया जाता है
लेकिन जहाँ सच्ची जिज्ञासा होती है, मेरी नज़र में हर ऐसी पोस्ट को जवाब मिलता है
शानदार। 1.20 में हमारी बड़ी umbrella app compilation काफ़ी तेज़ हो गई लगती है
जानना चाहता हूँ कि यह Gleam के मुकाबले कैसा है। या अब फिर Gleam की बजाय Elixir क्यों इस्तेमाल करें? Phoenix, ख़ासकर LiveView, Elixir की बड़ी ताकत लगती है
Gleam OTP की मौजूदा स्थिति मुझे नहीं पता, लेकिन आख़िरी बार जब मैंने देखा था, तब वह अच्छी नहीं थी
अगर आपको दोनों में से किसी से फ़र्क नहीं पड़ता और सिर्फ़ types मायने रखते हैं, तो Gleam इस्तेमाल करिए। लेकिन फिर सीधा Rust ही क्यों न इस्तेमाल करें?
उदाहरण के लिए, Gleam में JSON decoding/encoding काफ़ी verbose हो जाती है। Rust में आप serde derive कर देते हैं, और Elixir में एक function call काफ़ी होती है
Elixir का ecosystem ज़्यादा mature है। उदाहरण के लिए, आप Gleam में Phoenix या कोई और Gleam framework इस्तेमाल कर सकते हैं, लेकिन अनुभव वैसा नहीं होता
Gleam का Elixir पर बड़ा आकर्षण types हैं, और अब Elixir उस फ़ासले को कम कर रहा है। साथ ही यह JavaScript में compile भी कर सकता है, और Elixir में Hologram कुछ वैसा ही कर रहा है
निजी तौर पर मुझे Gleam का type system और Rust जैसी syntax ज़्यादा पसंद है, लेकिन इस समय मेरे सभी web development projects के लिए Elixir बेहतर विकल्प लगता है