Cairo में Type casting एक डेटा प्रकार (data type) से दूसरे में मानों (values) को परिवर्तित करने की प्रक्रिया है।
यह तब आवश्यक हो जाता है जब Cairo के सख्त टाइप सिस्टम के साथ काम किया जाता है, जहां फ़ंक्शन कॉल, वेरिएबल असाइनमेंट, कॉन्ट्रैक्ट इंटरेक्शन और डेटा ऑपरेशन्स के लिए स्पष्ट टाइप मैचिंग (explicit type matching) की आवश्यकता होती है।
Solidity की तुलना में Cairo टाइप रूपांतरण (type conversions) को संभालने में अधिक सतर्क दृष्टिकोण अपनाता है। यह उन मामलों को संभालने के स्पष्ट तरीके प्रदान करता है जहां कास्टिंग विफल हो सकती है, बजाय ऐसे रूपांतरणों की अनुमति देने के जो चुपचाप अनपेक्षित त्रुटियों (unintended errors) का कारण बन सकते हैं, जैसे कि डेटा ट्रंकेशन (data truncation)।
दोनों भाषाओं के बीच दृष्टिकोण में अंतर को स्पष्ट करने के लिए, uint32 प्रकार को uint8 प्रकार में परिवर्तित करने पर विचार करें:
Solidity उदाहरण:
contract Example {
function castingExample() public pure returns (uint8) {
uint32 largeNumber = 1000;
uint8 smallNumber = uint8(largeNumber);
return smallNumber;
}
}
Solidity में, कास्टिंग मॉड्युलो एरिथमेटिक (1000 % 2**8 = 232) का उपयोग करके चुपचाप largeNumber (1000) को smallNumber (232) में ट्रंकेट कर देती है। castingExample() फ़ंक्शन सफलतापूर्वक निष्पादित (execute) होता है और बिना किसी चेतावनी के 232 लौटाता है कि डेटा का नुकसान हुआ है।
Cairo उदाहरण:
fn casting_example() -> u8 {
let large_number: u32 = 1000;
let small_number: u8 = large_number.try_into().unwrap();
println!("Small number is : {}", small_number);
small_number
}
fn main(){
casting_example();
}
रनटाइम पर, try_into() यह जांचता है कि क्या large_number (1000) u8 (अधिकतम मान 255) में फिट हो सकता है। जब रूपांतरण विफल हो जाता है, तो यह None लौटाता है, और बाद में कॉल किया गया unwrap() "Option::unwrap failed." के साथ पैनिक (panic) हो जाता है, जो डेटा करप्शन की अनुमति देने के बजाय निष्पादन (execution) को तुरंत रोक देता है।
try_into().unwrap() सिंटैक्स को अगले भाग में विस्तार से समझाया गया है।
गारंटीकृत Conversions और विफल हो सकने वाले Conversions के बीच अंतर
Cairo टाइप कास्टिंग को दो मुख्य गुणों (traits) के माध्यम से संभालता है: सुरक्षित रूपांतरणों के लिए Into और ऐसे रूपांतरणों के लिए TryInto जो विफल हो सकते हैं।
Into Trait: अचूक (Infallible) type casting
Into trait का उपयोग उन रूपांतरणों के लिए किया जाता है जिनके सफल होने की गारंटी होती है। ये “सुरक्षित (safe)” रूपांतरण हैं जहां लक्ष्य प्रकार (target type) हमेशा स्रोत प्रकार (source type) से किसी भी मान का प्रतिनिधित्व कर सकता है। यह trait बिना किसी इम्पोर्ट स्टेटमेंट की आवश्यकता के हर Cairo प्रोग्राम में स्वचालित रूप से उपलब्ध है।
यहां एक उदाहरण दिया गया है जो छोटे से बड़े इंटीजर प्रकारों (integer types) में, और इंटीजर से Cairo के मूल (native) felt252 प्रकार में रूपांतरण दिखाता है:
fn main() {
let small_number: u8 = 100;
let large_number: u32 = small_number.into();
let num: u16 = 500;
let as_felt: felt252 = num.into();
}
यहां यह स्पष्ट है कि u8 प्रकार का small_number या u32 से छोटा कोई भी प्रकार larger_number में फिट हो सकता है, और felt252 में u256 (जो felt252 से बड़ा है) को छोड़कर सभी uint प्रकारों से कोई भी मान हो सकता है।
जब हम .into() का उपयोग करते हैं, तो हम Cairo कंपाइलर को बता रहे होते हैं, “हम जानते हैं कि यह रूपांतरण हमेशा काम करेगा, इसलिए बस इसे करें।” ऊपर दिए गए उदाहरणों में, small_number को u8 से u32 में और num को u16 से felt252 में परिवर्तित करने के सफल होने की गारंटी है क्योंकि लक्ष्य प्रकार स्रोत प्रकारों से कोई भी मान धारण कर सकते हैं।
हालाँकि, यदि हम एक बड़े प्रकार से छोटे प्रकार में परिवर्तित करने के लिए .into() का उपयोग करने का प्रयास करते हैं, तो Cairo कंपाइलर एक त्रुटि (error) देगा:
fn main() {
let large_number: u256 = 100;
let small_number: u32 = large_number.into(); // ERROR: Trait has no implementation in context: core::traits::Into::<core::integer::u256, core::integer::u32>
}
यह त्रुटि इसलिए होती है क्योंकि Cairo का Into trait केवल सुरक्षित रूपांतरणों के लिए लागू किया गया है जहां लक्ष्य प्रकार स्रोत प्रकार के सभी संभावित मानों को धारण कर सकता है। चूँकि u256 में u32 की तुलना में बहुत बड़ी वैल्यू रेंज (value range) है, इसलिए इस रूपांतरण के लिए कोई Into इम्प्लीमेंटेशन नहीं है, भले ही मान 100 u32 में फिट बैठता हो।
TryInto Trait: विफल हो सकने वाली (Fallible) type casting
TryInto trait उन रूपांतरणों के लिए उपयोग करने का सही तरीका है जो विफल हो सकते हैं यदि स्रोत मान सीमा (source value range) लक्ष्य प्रकार (target type) में फिट नहीं होती है। Into की तरह, यह trait भी बिना इम्पोर्ट स्टेटमेंट की आवश्यकता के स्वचालित रूप से उपलब्ध है।
TryInto एक Option एनम (enum) लौटाता है, जो या तो Some(converted_value) हो सकता है यदि रूपांतरण सफल रहा, या None यदि यह विफल रहा।
उस पहले के उदाहरण को आगे बढ़ाते हुए जहाँ 1000 (u32) सुरक्षित रूप से u8 में परिवर्तित नहीं हो सका, नीचे दिया गया try_convert_to_u8 फ़ंक्शन संभावित रूप से असुरक्षित टाइप रूपांतरणों के प्रति Cairo के दृष्टिकोण को दर्शाता है। यह फ़ंक्शन एक u32 मान लेता है और इसे u8 में बदलने का प्रयास करता है। यह कोड सफल रूपांतरणों (जब मान फिट बैठते हैं) और विफल रूपांतरणों (जब मान u8 की 0-255 सीमा के लिए बहुत बड़े होते हैं) दोनों को दिखाता है:
fn try_convert_to_u8(num: u32) {
// Attempt to convert u32 to u8 (returns Option<u8>)
let result: Option<u8> = num.try_into();
// Use 'match' to handle both success and failure cases
// 'match' is Cairo's pattern matching (like a switch statement that checks what's inside Option)
match result {
Option::Some(val) => {
// Conversion succeeded (val contains the converted u8 value)
println!("Successfully converted {} to u8: {}", num, val);
},
Option::None => {
// Conversion failed (number was too large for u8 (which holds 0-255))
println!("Conversion failed! {} is too big for u8 (max: 255)", num);
}
}
}
fn main() {
try_convert_to_u8(1000); // Will fail (too large for u8)
try_convert_to_u8(100); // Will succeed (fits in u8)
try_convert_to_u8(255); // Will succeed (maximum u8 value)
try_convert_to_u8(256); // Will fail (exceeds u8 maximum by 1)
}
try_convert_to_u8 फ़ंक्शन के अंदर, हम इनपुट num मान पर try_into() कॉल करते हैं, जो एक Option प्रकार लौटाता है जिसे हम result में स्टोर करते हैं।
match स्टेटमेंट Cairo का पैटर्न मैचिंग फ़ीचर है, जो अन्य भाषाओं के स्विच (switch) स्टेटमेंट के समान है। यह जांचता है कि Option के अंदर क्या है और परिणाम में कोई मान है या वह खाली है, इसके आधार पर कोड के एक विशिष्ट ब्लॉक को निष्पादित करता है। यदि रूपांतरण सफल रहा, तो हमें Some(val) मिलता है जिसमें परिवर्तित मान होता है, और हम एक सफलता संदेश (success message) प्रिंट करते हैं। यदि संख्या बहुत बड़ी होने के कारण रूपांतरण विफल हो जाता है, तो हमें None मिलता है, और हम विफलता की व्याख्या करते हुए एक त्रुटि संदेश प्रिंट करते हैं।
main() फ़ंक्शन में, हम यह प्रदर्शित करने के लिए चार अलग-अलग परिदृश्यों (scenarios) का परीक्षण करते हैं कि रूपांतरण विभिन्न इनपुट मानों के साथ कैसे व्यवहार करता है।
जब हम try_convert_to_u8(1000) कॉल करते हैं, तो नीचे दिया गया आरेख (diagram) दिखाता है कि कैसे रूपांतरण Option<u8> में None लौटाता है क्योंकि 1000 अधिकतम मान u8 (255) से अधिक है:

चूंकि रूपांतरण ने None लौटाया है, इसलिए match स्टेटमेंट पता लगाता है कि यह खाली है और Option::None ब्रांच को निष्पादित करता है, जिससे त्रुटि संदेश "Conversion failed! 1000 is too big for u8 (max: 255).” प्रिंट होता है।
इसके बाद, जब try_convert_to_u8(100) चलता है, तो नीचे दिया गया आरेख दिखाता है कि रूपांतरण Option<u8> में Some(100) कैसे लौटाता है क्योंकि 100, 0-255 की मान्य सीमा (valid range) के भीतर फिट बैठता है:

चूंकि रूपांतरण सफल रहा, match स्टेटमेंट Option::Some(val) ब्रांच को निष्पादित करता है, जिससे “Successfully converted 100 to u8: 100.” प्रिंट होता है।
into() या try_into() का उपयोग कब करें
into() का उपयोग इनके लिए करें:
- छोटे प्रकारों को बड़े प्रकारों में बदलने के लिए (उदा.,
u32सेu64) - कोई भी रूपांतरण जहाँ डेटा हानि (data loss) असंभव है
into()स्पष्ट रूप से बड़े प्रकारों से छोटे प्रकारों में कास्टिंग की अनुमति नहीं देता है, भले ही विशिष्ट मान लक्ष्य सीमा (target range) में फिट बैठता हो।
try_into() का उपयोग इनके लिए करें:
- बड़े प्रकारों को छोटे प्रकारों में बदलने के लिए (
u32सेu8) - कोई भी रूपांतरण जहाँ मान फिट नहीं हो सकता है
- जब आप पैनिक (panicking) के बजाय रूपांतरण विफलताओं को इनायत से (gracefully) संभालना चाहते हैं, तो
matchके साथtry_into()का उपयोग करें।
Cairo के कास्टिंग तंत्र (casting mechanisms) की समझ के साथ, अब हम यह देख सकते हैं कि ये traits विशिष्ट रूपांतरण परिदृश्यों (conversion scenarios) पर कैसे लागू होते हैं।
felt252 से uints
felt252 को अनसाइन्ड इंटीजर प्रकारों (unsigned integer types) में बदलना Cairo में एक सामान्य ऑपरेशन है क्योंकि felt252 मूल प्रकार (native type) है। रूपांतरण दृष्टिकोण इस बात पर निर्भर करता है कि हम एक बड़े या छोटे इंटीजर प्रकार में परिवर्तित कर रहे हैं या नहीं।
यहाँ एक उदाहरण है जो felt252 मान (felt_value) को u256 (as_u256) में परिवर्तित करता है:
fn main() {
let felt_value: felt252 = 42615;
let as_u256: u256 = felt_value.into();
}
इस रूपांतरण के सफल होने की गारंटी है क्योंकि u256 किसी भी felt252 मान को धारण कर सकता है, यही कारण है कि हम .try_into() के बजाय .into() का उपयोग कर सकते हैं।
felt252 को छोटे इंटीजर प्रकारों में बदलने के लिए try_into() की आवश्यकता होती है क्योंकि felt252 मान लक्ष्य प्रकार की सीमा (target type’s range) से अधिक हो सकता है।
यह फ़ंक्शन felt252 को u8 में बदलने का प्रयास करता है, लेकिन यदि मान 255 से बड़ा है तो यह पैनिक (panic) हो जाएगा:
fn convert_felt_to_small_uint(felt_value: felt252) -> u8 {
felt_value.try_into().unwrap()
}
convert_felt_to_small_uint फ़ंक्शन एक felt252 मान लेता है, इसे u8 में बदलने का प्रयास करता है, और विफल होने पर पैनिक हो जाता है। यह try_into() द्वारा लौटाए गए Option से u8 मान निकालने के लिए .unwrap() का उपयोग करता है। यदि felt252 मान 255 से अधिक है, तो रूपांतरण None लौटाता है और .unwrap() के कारण प्रोग्राम पैनिक हो जाएगा।
एक सुरक्षित तरीका यह है कि पैनिक किए बिना संभावित रूपांतरण विफलताओं (conversion failures) को स्पष्ट रूप से संभाला जाए। निम्नलिखित कोड पैनिक करने के बजाय Option<u8> लौटाने वाला एक फ़ंक्शन बनाकर उचित त्रुटि हैंडलिंग (error handling) दिखाता है, फिर एक सफल रूपांतरण (100) और एक विफल रूपांतरण (1000) दोनों का परीक्षण करता है, जिसमें प्रत्येक परिणाम को उचित रूप से संभालने के लिए match स्टेटमेंट होते हैं:
fn safe_convert_felt_to_u8(felt_value: felt252) -> Option<u8> {
felt_value.try_into()
}
fn main() {
let small_felt: felt252 = 100;
let large_felt: felt252 = 1000;
let small_as_u8 = safe_convert_felt_to_u8(small_felt); // Returns Some(100)
println!("Small conversion result: {:?}", small_as_u8);
let large_as_u8 = safe_convert_felt_to_u8(large_felt); // Returns None
// handle the successful conversion
match small_as_u8 {
Option::Some(val) => println!("Successfully converted 100 to u8: {}", val),
Option::None => println!("Small conversion failed"),
}
// handle the failed conversion
match large_as_u8 {
Option::Some(val) => println!("Converted: {}", val),
Option::None => println!("Conversion failed: 1000 is too large for u8"),
}
}
safe_convert_felt_to_u8, felt252 मान लेता है और Option<u8> लौटाता है। ध्यान दें कि यह .unwrap() का उपयोग नहीं करता है; यह try_into() से सीधे Option लौटाता है, जिससे कॉलर को यह तय करने की सुविधा मिलती है कि संभावित विफलताओं को कैसे संभालना है।
main फ़ंक्शन में, हम दो परिदृश्यों (scenarios) का परीक्षण करते हैं:
- 100 को
u8में बदलना: यह सफल होता है क्योंकि 100,u8की सीमा (0-255) के भीतर फिट बैठता है, इसलिएsmall_as_u8मेंSome(100)होता है - 1000 को
u8में बदलना: यह विफल रहता है क्योंकि 1000,u8के 255 के अधिकतम मान से अधिक है, इसलिएlarge_as_u8मेंNoneहोता है
पहला match स्टेटमेंट सफल रूपांतरण को संभालता है। चूँकि small_as_u8 में Some(100) होता है, यह Option::Some(val) ब्रांच से मेल खाता है और परिवर्तित मान के साथ सफलता संदेश (success message) प्रिंट करता है।
दूसरा match स्टेटमेंट विफल रूपांतरण को संभालता है। चूँकि large_as_u8 में None होता है, यह Option::None ब्रांच से मेल खाता है और एक त्रुटि संदेश प्रिंट करता है जो बताता है कि रूपांतरण क्यों विफल रहा।
यह दिखाता है कि बिना पैनिक किए सफल और विफल दोनों रूपांतरणों को इनायत से (gracefully) कैसे संभालना है, जिससे हमें अपने प्रोग्राम में त्रुटि हैंडलिंग पर पूरा नियंत्रण मिलता है।
uints से Address Type
Cairo इंटीजर प्रकारों (integer types) से पतों (addresses) में सीधे रूपांतरण की अनुमति नहीं देता है। इसके बजाय, रूपांतरणों को मध्यवर्ती प्रकार (intermediate type) के रूप में felt252 के माध्यम से होना चाहिए। उपयोगकर्ता आईडी (user IDs), संख्यात्मक पहचानकर्ताओं (numeric identifiers) के साथ काम करते समय, या स्मार्ट कॉन्ट्रैक्ट्स में इंटीजर गणनाओं से पते (addresses) प्राप्त करते समय uints को पतों में बदलना आवश्यक हो जाता है।
रूपांतरण प्रक्रिया में दो चरण शामिल हैं: पहले इंटीजर को felt252 में बदलना, फिर felt252 को ContractAddress में बदलना:
use starknet::ContractAddress;
fn user_address(user_id: u64) -> ContractAddress {
let address_felt: felt252 = user_id.into();
address_felt.try_into().unwrap()
}
user_address फ़ंक्शन एक u64 पैरामीटर user_id स्वीकार करता है। यह पहले .into() का उपयोग करके u64 मान को felt252 में परिवर्तित करता है जो हमेशा सफल होता है क्योंकि felt252 किसी भी u64 मान को धारण कर सकता है और इसे address_felt में संग्रहीत कर सकता है। फिर यह .try_into().unwrap() का उपयोग करके felt252 address_felt को ContractAddress में परिवर्तित करता है।
हम .try_into() का उपयोग करते हैं क्योंकि यह felt252 से ContractAddress में उपलब्ध एकमात्र रूपांतरण विधि (conversion method) है। .unwrap() परिणाम निकालता है लेकिन यदि रूपांतरण विफल रहता है तो पैनिक (panic) हो जाएगा।
ऊपर दिए गए कोड उदाहरण में, try_into() विधि Option<ContractAddress> लौटाती है; या तो Some(address) यदि रूपांतरण सफल होता है या None यदि यह विफल रहता है। .unwrap() विधि Some() से वास्तविक ContractAddress मान निकालती है, लेकिन यदि रूपांतरण विफल हो गया और None लौटाया तो यह पैनिक हो जाएगी।
u256 को परिवर्तित करने के लिए अतिरिक्त सावधानी की आवश्यकता होती है क्योंकि u256 मान felt252 सीमा (range) से अधिक हो सकते हैं, और ContractAddress की मान्य सीमा (valid range) [0, 2**251) और भी छोटी होती है। इसका मतलब है कि दोनों रूपांतरण चरण संभावित रूप से विफल हो सकते हैं।
उन मामलों के लिए जहाँ हमें विश्वास है कि मान फिट होगा, मान लीजिए कि जब मान felt252 सीमा के भीतर है, हम प्रत्यक्ष दृष्टिकोण (direct approach) का उपयोग कर सकते हैं:
fn convert_u256_to_address(value: u256) -> ContractAddress {
// First step: convert u256 to felt252 (will panic if value exceeds felt252 range)
let address_felt: felt252 = value.try_into().unwrap();
// Second step: convert felt252 to ContractAddress (will panic if outside valid address range)
address_felt.try_into().unwrap()
}
जब मनमाने (arbitrary) u256 मानों से निपटा जाता है जो मान्य सीमा से बाहर हो सकते हैं, तो संभावित विफलताओं को स्पष्ट रूप से संभालना बेहतर होता है:
fn safe_convert_u256_to_address(value: u256) -> Option<ContractAddress> {
// First step: try to convert u256 to felt252 (might fail if value is too large)
match value.try_into() {
Option::Some(felt_val) => {
// u256 to felt252 conversion succeeded
let address_felt: felt252 = felt_val;
// Second step: try to convert felt252 to ContractAddress
// This can also fail if the felt252 value is outside valid address range
address_felt.try_into()
}
Option::None => {
// u256 to felt252 conversion failed (value too large for felt252)
Option::None
}
}
}
रूपांतरण विफलता पर पैनिक होने के बजाय, safe_convert_u256_to_address उन इनपुट के लिए None लौटाता है जो ContractAddress सीमा से अधिक हैं, जिससे कॉलर को बड़े आकार के इनपुट को इनायत से (gracefully) संभालने की अनुमति मिलती है।
ByteArray और String Casting
Cairo में स्ट्रिंग अभ्यावेदन (string representations) और संख्यात्मक प्रकारों (numeric types) के बीच कनवर्ट करने में Cairo के स्ट्रिंग प्रकारों के साथ काम करना शामिल है: छोटी स्ट्रिंग्स (जो felt252 हैं) और लंबी स्ट्रिंग्स के लिए ByteArray।
Short strings
fn main() {
let string_as_felt: felt252 = 'Hello';
let hex_representation: felt252 = 0x48656c6c6f;
println!("String: {}", string_as_felt);
println!("Hex form: {}", hex_representation);
}
जब यह कोड चलता है, तो आप देखेंगे कि Cairo में छोटी स्ट्रिंग्स (short strings) सीधे felt252 मानों के रूप में संग्रहीत होती हैं।

कोई रूपांतरण नहीं हो रहा है; 'Hello' और इसके हेक्साडेसिमल समकक्ष 0x48656c6c6f समान felt252 मान हैं।
Short strings से uints
यहाँ एक उदाहरण है जो एक वर्ण (character) (जो felt252 के रूप में संग्रहीत है) को u8 के रूप में इसके ASCII मान में परिवर्तित करता है:
fn main() {
let char_a: felt252 = 'A';
let char_as_u8: u8 = char_a.try_into().unwrap();
println!("Character 'A' as u8: {}", char_as_u8);
}
जब यह कोड चलता है, तो यह टर्मिनल में “Character ‘A’ as u8: 65” प्रदर्शित करता है क्योंकि वर्ण मान (character value) लक्ष्य प्रकार में फिट बैठता है। यदि मान फिट नहीं होता है, तो प्रोग्राम पैनिक हो जाएगा, इसलिए ऐसे मामलों को संभालना महत्वपूर्ण है जब रूपांतरण की सफलता अनिश्चित हो।
ByteArray ऑपरेशन्स
ByteArray डेटा को परिवर्तित करने के लिए, इंडेक्सिंग के माध्यम से व्यक्तिगत बाइट्स तक पहुँचा जाता है और प्रत्येक बाइट को अलग से परिवर्तित किया जाता है।
ByteArray प्रकार मुख्य रूप से 31 बाइट्स से लंबी स्ट्रिंग्स को संभालने के लिए है, न कि संख्यात्मक प्रकार के रूपांतरणों के लिए।
ध्यान दें कि ByteArray में व्यक्तिगत बाइट्स (individual bytes) तक पहुंचने पर u8 प्राप्त होता है। जब ByteArray से व्यक्तिगत वर्णों (characters) के साथ संख्यात्मक मानों (numeric values) के रूप में काम करने की आवश्यकता होती है, तो उन्हें इंडेक्स द्वारा निकाला जा सकता है और अन्य संख्यात्मक प्रकारों जैसे u32 या felt252 में परिवर्तित किया जा सकता है। निम्नलिखित उदाहरण पर विचार करें:
fn main() {
let text: ByteArray = "Cairo";
let first_byte = text[0];
let third_byte = text[2];
let byte_as_u32: u32 = first_byte.into();
let byte_as_felt: felt252 = third_byte.into();
println!("First byte 'C' as u32: {}", byte_as_u32);
println!("Third byte 'i' as felt252: {}", byte_as_felt);
}
ByteArray “Cairo” को एक्सेस किया जाता है जहां पहले वर्ण (character), ‘C,’ को text[0] का उपयोग करके एक्सेस किया जाता है, जो एक u8 मान लौटाता है। इसे फिर .into() का उपयोग करके u32 में बदल दिया जाता है, जिसके सफल होने की गारंटी है क्योंकि u32 किसी भी u8 मान को धारण कर सकता है। इसी तरह, text[2] पर तीसरे वर्ण ‘i’ को felt252 में बदल दिया जाता है।
इस तरह, हम बाइट स्तर (byte level) पर ByteArray सामग्री के साथ काम करते हैं और व्यक्तिगत वर्णों को आपकी आवश्यकता वाले संख्यात्मक प्रकारों में परिवर्तित करते हैं।
अधिकांश समय, यदि हमारे पास ByteArray है, तो हम शायद इसे स्ट्रिंग डेटा के रूप में रखना चाहेंगे क्योंकि ByteArray संख्यात्मक गणना के बजाय टेक्स्ट को संग्रहीत करने और हेरफेर करने के लिए अनुकूलित (optimized) है।
bool casting
Cairo डिज़ाइन द्वारा बूलियन (boolean) मानों (true/false) को संख्यात्मक प्रकारों से अलग रखता है लेकिन स्वचालित रूप से .into() का उपयोग करके बूलियन मानों को felt252 में बदलने की अनुमति देता है, जहाँ true, 1 बन जाता है और false, 0 बन जाता है। हालाँकि, स्वचालित कास्टिंग विधियों का उपयोग करके बूलियंस को सीधे u32, u64 आदि जैसे इंटीजर प्रकारों में नहीं बदला जा सकता है:
fn main() {
let flag: bool = true;
// This works, bool to felt252:
let as_felt: felt252 = flag.into(); // Works: true becomes 1, false becomes 0
// This will cause a compilation error:
// let as_u32: u32 = flag.into(); // ERROR: Trait has no implementation in context: core::traits::Into::<core::bool, core::integer::u32>.
// Manual conversion for integers:
let as_u32: u32 = if flag {
1
} else {
0
};
}
संख्याओं को स्वचालित रूप से बूलियंस में वापस कास्ट (cast) नहीं किया जा सकता है। इसके लिए स्पष्ट तुलनाओं (explicit comparisons) की आवश्यकता होती है जैसा कि नीचे दिखाया गया है:
fn main() {
let number: u32 = 1;
let felt_num: felt252 = 1;
// These will cause compilation errors:
// let back_to_bool: bool = number.into(); // ERROR: Trait has no implementation in context: core::traits::Into::<core::integer::u32, core::bool>.
// let felt_to_bool: bool = felt_num.into(); // ERROR: Trait has no implementation in context: core::traits::Into::<core::felt252, core::bool>.
// Manual conversion:
let back_to_bool: bool = number != 0;
let felt_to_bool: bool = felt_num != 0;
}
बूलियंस को सीधे ऐरे इंडेक्स (array indices) के रूप में या अंकगणितीय ऑपरेशन्स (arithmetic operations) में भी उपयोग नहीं किया जा सकता है:
fn main() {
let my_array = array![10, 20];
let index: bool = true;
// These will cause compilation errors:
// let value = my_array[index];
// let result = index + 1;
// Conversions work:
let numeric_index: u32 = if index {
1
} else {
0
};
let value = my_array[numeric_index];
}
इसलिए मुख्य बिंदु यह है: bool से felt252 स्वचालित रूप से काम करता है, लेकिन bool से इंटीजर प्रकारों के लिए मैन्युअल रूपांतरण (manual conversion) की आवश्यकता होती है, और विपरीत दिशा (reverse direction) में कोई स्वचालित कास्टिंग काम नहीं करती है।
ज्यादातर मामलों में, बेहतर टाइप सुरक्षा (type safety) और कोड स्पष्टता (code clarity) के लिए बूलियंस को बूलियंस के रूप में ही रहना चाहिए।
निष्कर्ष
Cairo में Type casting स्वचालित रूपांतरण (automatic conversion) पर सुरक्षा और स्पष्टता (explicitness) को प्राथमिकता देती है। यह गारंटीकृत रूपांतरणों (guaranteed conversions) के लिए Into और विफल हो सकने वाले रूपांतरणों के लिए TryInto का उपयोग करता है, जिससे संभावित त्रुटियों (potential errors) को स्पष्ट रूप से संभालने के लिए बाध्य किया जाता है।
यह दृष्टिकोण अन्य भाषाओं में आम चुपचाप होने वाले डेटा हानि (silent data loss) को रोकता है और उत्पादन (production) तक पहुंचने से पहले बग (bugs) को पकड़ लेता है। Cairo के स्पष्ट रूपांतरणों (explicit conversions) का मतलब है कि आपके स्मार्ट कॉन्ट्रैक्ट अनुमानित (predictably) रूप से व्यवहार करते हैं, यहां तक कि अप्रत्याशित डेटा को संभालते समय भी।
Solidity के विपरीत, जिसे टाइप रूपांतरण के लिए मैन्युअल सुरक्षा जांच (manual safety checks) की आवश्यकता होती है, Cairo सीधे Option प्रकारों के माध्यम से अपने कास्टिंग सिस्टम में त्रुटि हैंडलिंग (error handling) का निर्माण करता है।
हालांकि Cairo की रूपांतरण आवश्यकताओं (conversion requirements) में इम्प्लिसिट (implicit) कास्टिंग की तुलना में अधिक कोड की आवश्यकता होती है, लेकिन यह स्पष्टता (explicitness) अधिक विश्वसनीय स्मार्ट कॉन्ट्रैक्ट बनाती है।
यह लेख Cairo Programming on Starknet पर एक ट्यूटोरियल सीरीज़ का हिस्सा है।