
«Parse, don't validate»-ը Rust-ում. ինչպես ստուգումը դարձնել տիպ
Էլի Բենդերսկին վերանայում է «Parse, don't validate» գաղափարը Rust-ի համար. տվյալները պետք է ոչ թե պարզապես ստուգել, այլ վերածել տիպի, որի երաշխիքը հնարավոր չէ խախտել։
Էլի Բենդերսկին իր բլոգում հրապարակել է նոր էսսե, որը վերադառնում է Ալեքսիս Քինգի 2019 թվականի հոդվածի գաղափարին։ Haskell-ի համար գրված բնագրում ասվում է, որ կոդը չպետք է պարզապես ստուգի պայմանը և ապա վստահի դրան, այլ տվյալները վերածի այնպիսի տիպի, որի համար երաշխավորված հատկության խախտումն անհնարին է։ Բենդերսկին նույն տրամաբանությունը կիրառում է Rust-ի վրա և ուսանելի օրինակներ փնտրում լեզվի ստանդարտ գրադարանում ու հայտնի նախագծերում։
Վեկտոր, որը չի կարող դատարկ լինել
Մեկնարկային կետը սովորական Vec-ն է և նրա first() մեթոդը, որը վերադարձնում է ոչ պարտադիր հղում, քանի որ վեկտորը կարող է ընդհանրապես տարր չպարունակել։ Բենդերսկիի օրինակում ֆունկցիան CONFIG_DIRS միջավայրի փոփոխականից կարդում է կարգավորումների պանակների ցանկը և մերժում դատարկ արդյունքը, սակայն կանչող կոդը դեռ ստիպված է գրել ճյուղ այն դեպքի համար, որը երբեք չի առաջանա։ Հեղինակը նման ինվարիանտները համեմատում է ժամացույցի մեխանիզմով ռումբի հետ. կոմպիլյատորը դրանք չի ստուգում, ուստի հետագայում դրանք կարող են լուռ խախտվել։ Լուծումը առանձին տիպն է, օրինակ nonempty crate-ի NonEmpty-ը, որը դատարկ արժեքի կոնստրուկտոր չունի, իսկ first()-ը վերադարձնում է սովորական հղում։ Ստուգված Vec վերադարձնելը վալիդացիա է, իսկ NonEmpty վերադարձնելը՝ փարսինգ, եթե փարսինգը հասկանանք լայն իմաստով՝ տվյալների մի ձևաչափից մյուսին փոխակերպում։
Խողովակաշարեր, ուղիներ և աստիճանական ճշգրտում
Այնուհետև էսսեն դուրս է գալիս խաղալիք կոդի սահմաններից։ posixutils-rs նախագծում, որը POSIX-ի հիմնական գործիքների Rust-ով վերաշարադրումն է, shell-ի խողովակաշարի հրամանները պահվում են NonEmpty-ում, ուստի վերլուծված խողովակաշարը միշտ պարունակում է առնվազն մեկ հրաման, իսկ վերլուծիչը None է վերադարձնում միայն այն դեպքում, երբ գործարկելու բան չկա։ rust-analyzer-ն առանձին տիպ ունի բացարձակ ֆայլային ուղու համար. փոխակերպումը ձախողվում է, եթե ուղին բացարձակ չէ, և հետագա կոդը հենվում է տիպի վրա, այլ ոչ թե նորից ստուգում է պայմանը։ Բենդերսկին սա անվանում է աստիճանական փարսինգ. ուղին նախ camino crate-ի օգնությամբ հաստատվում է որպես վավեր UTF-8, և միայն դրանից հետո՝ որպես բացարձակ։
Ոչ զրոյական թվեր և JSON
Rust-ի ստանդարտ գրադարանում կա ընդհանուր NonZero տիպը աննշան ամբողջ թվերի համար, որոնք հաստատ զրո չեն։ available_parallelism ֆունկցիան հաջողության դեպքում վերադարձնում է հենց այդպիսի արժեք, իսկ NonZero հայտարարով բաժանումը փաստաթղթավորված է որպես գործողություն, որը չի կարող պանիկա առաջացնել։ Կա նաև լրացուցիչ առավելություն. զրոն անվավեր բիթային նախշ է այս տիպի համար, ուստի ոչ պարտադիր NonZero-ն զբաղեցնում է ճիշտ նույն տեղը, ինչ սովորական ամբողջ թիվը։ Նույն գաղափարը երևում է նաև JSON-ի վերլուծության մեջ. serde-ի միջոցով կարգավորումների կառուցվածքը կարելի է նկարագրել այնպես, որ աշխատողների թիվը լինի ոչ զրոյական, իսկ ռեժիմը՝ երկու արժեք ունեցող enum. ապասերիալիզացիան միանգամից ստուգում է դաշտերի տիպերը, թույլատրելի արժեքները և զրոյի արգելքը։ Դինամիկ լեզուներում գործընթացը շատ ավելի ձեռքի աշխատանք է. Python-ի json.loads-ը վերադարձնում է բառարան և ստուգումը թողնում է կանչողին, իսկ Pydantic-ի նման գրադարանները մոտենում են Rust-ի մոտեցմանը, սակայն ամենուր չեն օգտագործվում։
SiTech — AI-ով հզորացված վեբ մշակում
Ստեղծում ենք արագ ու ժամանակակից կայքեր և AI-ը ներդնում իրական բիզնես գործընթացներում։ Ունե՞ք նախագիծ կամ հարց։ Ուրախ կլինենք օգնել։