Result Type — एक कंटेनर प्रकार है जो किसी ऑपरेशन के परिणाम को दर्शाता है जो सफलता (Success) या विफलता (Failure) के साथ पूरा हो सकता है। एक्सेप्शन के विपरीत, Result त्रुटि को स्टैक अनवाइंडिंग के बिना एक सामान्य मान के रूप में पास करता है, जिससे अपेक्षित त्रुटियों का प्रबंधन अधिक सुरक्षित और संयोजनीय बनता है। Apple Swift Documentation (2026) के अनुसार, Swift में Result<Success, Failure> प्रोग्राम निष्पादन को बाधित किए बिना map और flatMap के माध्यम से स्वचालित त्रुटि प्रबंधन के साथ संचालन की श्रृंखला बनाने की अनुमति देता है।
मुख्य बिंदु
Result Type एक जेनेरिक प्रकार है जो किसी ऑपरेशन के परिणाम को समाहित करता है जो सफल या असफल हो सकता है। एक्सेप्शन के विपरीत, जहाँ त्रुटि सामान्य प्रवाह को बाधित करती है और catch ब्लॉक खोजने के लिए स्टैक अनवाइंडिंग की आवश्यकता होती है, Result त्रुटि को एक सामान्य मान के रूप में पास करता है — कॉल करने वाले को हमेशा एक ऑब्जेक्ट मिलता है और वह तय करता है कि उसे कैसे संभालना है। यह विशेष रूप से अपेक्षित त्रुटियों के लिए उपयोगी है: अमान्य इनपुट, व्यावसायिक नियम, सर्वर अस्वीकृति, जहाँ एक्सेप्शन बहुत भारी तंत्र होगा।
Result की अवधारणा कार्यात्मक प्रोग्रामिंग से उत्पन्न हुई है, जहाँ समान प्रकारों को Either (या Left/Right) कहा जाता है। Swift में, Result Swift 5.0 में एक मानक प्रकार बन गया; Kotlin में, Result<T> मानक पुस्तकालय में दिखाई दिया; Dart 3.0 में, अंतर्निर्मित Result<T> पेश किया गया। प्रत्येक कार्यान्वयन कंटेनर के साथ काम करने के लिए विधियाँ प्रदान करता है: map (सफलता मान का रूपांतरण), flatMap (Result फ़ंक्शन की श्रृंखला), mapError (त्रुटि का रूपांतरण), fold (दोनों मामलों को संभालना)। Result Type मोबाइल डेवलपमेंट में कार्यात्मक त्रुटि प्रबंधन की आधारशिला है, जो अपेक्षित परिदृश्यों के लिए try-catch का विकल्प है।
Result का मुख्य लाभ संयोजनीयता है। आप कई संचालन, जिनमें से प्रत्येक विफल हो सकता है, को बिना नेस्टेड try-catch ब्लॉक के एक श्रृंखला में जोड़ सकते हैं। यदि श्रृंखला में कोई भी संचालन Failure के साथ विफल होता है, तो पूरी श्रृंखला बाधित हो जाती है और Failure लौटाती है — बिना एक if शर्त या catch ब्लॉक के। यह कोड को रैखिक और पढ़ने योग्य बनाता है, विशेष रूप से कई अनुक्रमिक API अनुरोधों या व्यावसायिक नियम जाँच वाले परिदृश्यों में।
Swift में, Result<Success, Failure> दो केस वाला एक enum है: .success(Success) और .failure(Failure), जहाँ Failure Error प्रोटोकॉल द्वारा प्रतिबंधित है। Swift Result map, flatMap, mapError और get विधियों वाला एक पूर्ण कार्यात्मक प्रकार है। get एक विशेष विधि है: यदि परिणाम सफल है तो यह Success मान लौटाती है, और यदि Failure है तो त्रुटि फेंकती है। यह Result को कार्यात्मक और एक्सेप्शन-आधारित शैलियों के बीच एक पुल के रूप में कार्य करने की अनुमति देता है: श्रृंखला में map/flatMap के माध्यम से संभालें, और अंत में throws कोड के साथ एकीकृत करने के लिए do-catch के साथ get का उपयोग करें।
Swift Result जेनेरिक पैरामीटर वाला एक enum है, जो कंपाइलर को switch या do-catch के माध्यम से व्यापक हैंडलिंग लागू करने की अनुमति देता है। यदि आप NetworkError enum में एक नया केस जोड़ते हैं, तो कंपाइलर सभी switch अभिव्यक्तियों में त्रुटि उत्पन्न करेगा जहाँ उस केस को संभाला नहीं गया है। व्यापक जाँच एक्सेप्शन पर Result का मुख्य लाभ है: कंपाइलर गारंटी देता है कि बिल्ड समय पर सभी संभावित त्रुटियों का ध्यान रखा गया है। इसके विपरीत, Swift में कंपाइलर द्वारा एक्सेप्शन की जाँच नहीं की जाती है (केवल throws घोषित किया जाता है, लेकिन त्रुटि प्रकार नहीं)।
enum NetworkError: Error {
case badURL
case requestFailed(String)
case decodingFailed
}
func fetchUser(id: Int) -> Result<User, NetworkError> {
guard let url = URL(string: "https://api.example.com/users/\(id)") else {
return .failure(.badURL)
}
let result = performRequest(url: url)
switch result {
case let .success(data):
if let user = try? JSONDecoder().decode(User.self, from: data) {
return .success(user)
}
return .failure(.decodingFailed)
case let .failure(error):
return .failure(.requestFailed(error.localizedDescription))
}
}
// switch के साथ उपयोग
let result = fetchUser(id: 42)
switch result {
case .success(let user):
showUser(user)
case .failure(.badURL):
logError("Invalid URL")
case .failure(.requestFailed(let msg)):
showAlert(msg)
case .failure(.decodingFailed):
logError("Decoding error")
}
Result<Success, Failure> प्रकार स्तर पर त्रुटि को टाइप करने की अनुमति देता है: fetchUser फ़ंक्शन Result<User, NetworkError> लौटाता है, जहाँ NetworkError तीन केस वाला एक ठोस enum है। कॉल करने वाला व्यापक कवरेज के साथ switch के माध्यम से प्रत्येक केस को संभालता है — कंपाइलर जाँच करता है कि सभी वेरिएंट संभाले गए हैं। व्यापक switch एक्सेप्शन पर Result का एक मुख्य लाभ है: कंपाइलर गारंटी देता है कि आप .badURL, .requestFailed या .decodingFailed को संभालना नहीं भूलेंगे। एक्सेप्शन के साथ, कंपाइलर हैंडलिंग की आवश्यकता नहीं होती है, और कोड समीक्षा में गायब catch(.badURL) आसानी से छूट सकता है।
Kotlin में, Result<T> मानक पुस्तकालय का एक अंतर्निर्मित प्रकार है जो सफलता (T) या त्रुटि (Throwable) दर्शाता है। Swift के विपरीत, Kotlin Result एक ठोस त्रुटि प्रकार निर्दिष्ट करने की अनुमति नहीं देता है — केवल Throwable। यह सरलता के लिए किया गया है लेकिन when अभिव्यक्ति के माध्यम से अतिरिक्त त्रुटि प्रकार जाँच की आवश्यकता होती है। Kotlin Result fold (दोनों मामलों को संभालना), getOrNull (सफलता या null), getOrDefault (सफलता या डिफ़ॉल्ट), map, recover, andThen फ़ंक्शन का समर्थन करता है। Kotlin की एक विशेषता: Result फ़ंक्शन सीमाओं के पार सीधे प्रसार के लिए अभिप्रेत नहीं है — इसे अतिरिक्त अनुकूलन के बिना Android SDK विधियों या Kotlin Coroutines API के लिए रिटर्न प्रकार के रूप में उपयोग नहीं किया जा सकता है।
fun parseJson(input: String): Result<JsonObject> {
return runCatching {
JsonParser.parseString(input).asJsonObject()
}
}
fun validateEmail(email: String): Result<String> {
return if (email.contains("@")) {
Result.success(email.trim())
} else {
Result.failure(IllegalArgumentException("Invalid email"))
}
}
data class SignupData(val name: String, val email: String)
fun processSignup(name: String, email: String): SignupResult {
return validateEmail(email).fold(
onSuccess = { validateName(name) },
onFailure = { SignupResult.Error("Invalid email") }
)
}
runCatching Kotlin में एक सुविधाजनक रैपर है जो किसी भी एक्सेप्शन को पकड़ता है और Result.failure लौटाता है। validateEmail सत्यापन के आधार पर Result.success या Result.failure लौटाता है। fold दोनों मामलों को संक्षिप्त रूप से संभालता है: Success पर, अगला सत्यापन फ़ंक्शन कॉल किया जाता है; Failure पर, SignupResult.Error लौटाया जाता है। महत्वपूर्ण: Kotlin Result डेटा क्लास फ़ील्ड में भंडारण या suspend फ़ंक्शन सीमाओं के पार सीधे संचरण के लिए अभिप्रेत नहीं है — Jetpack Compose या MVVM में UI स्थितियों का प्रतिनिधित्व करने के लिए कस्टम सील्ड क्लास (Success/Error/Loading) का उपयोग करें।
Dart 3.0 से, मानक पुस्तकालय में एक अंतर्निर्मित Result<T> शामिल है — दो कंस्ट्रक्टर वाली एक सील्ड क्लास: T.ok() (सफलता) और Error.error() (Object और StackTrace के साथ त्रुटि)। Dart 3.0 से पहले, Flutter डेवलपर्स dartz पैकेज से Either<L, R> या कस्टम सील्ड क्लास का उपयोग करते थे। Dart में अंतर्निर्मित Result न्यूनतम है: यह सीधे map/flatMap प्रदान नहीं करता है — इन फ़ंक्शन को when के माध्यम से या एक्सटेंशन विधियों का उपयोग करके लागू करने की आवश्यकता है। गंभीर कार्यात्मक हैंडलिंग के लिए, fpdart से Either map, flatMap, mapLeft, fold, andThen और bind ऑपरेटरों के समर्थन के साथ एक अधिक शक्तिशाली समाधान बना हुआ है।
Either<L, R> fpdart पैकेज से एक वाम-पक्षीय प्रकार है, जहाँ Left त्रुटि है और Right सफलता है। अंतर्निर्मित Result<T> के विपरीत, Either प्रकार पैरामीटर स्तर (L) पर त्रुटि को टाइप करता है, जो संकलन समय पर त्रुटि प्रकार भेदभाव की अनुमति देता है। fpdart पैकेज कार्यात्मक संयोजकों का एक पूर्ण सेट प्रदान करता है: map (Right -> Right), mapLeft (Left -> Left), flatMap (bind — नेस्टेड Either), andThen (बिना रूपांतरण के श्रृंखला), fold (Either से बाहर निकलना), getOrElse (डिफ़ॉल्ट मान)। कार्यात्मक दृष्टिकोण वाले Flutter अनुप्रयोगों के लिए, Either वास्तविक मानक है।
import 'dart:convert';
import 'package:fpdart/fpdart.dart';
class UserService {
Either<AppError, User> fetchUser(String id) {
try {
final response = await http.get(
Uri.parse('https://api.example.com/users/$id')
);
if (response.statusCode == 200) {
final user = User.fromJson(
json.decode(response.body)
);
return Either.of(user);
}
return Either.left(
AppError.serverError(response.statusCode)
);
} on SocketException catch (e) {
return Either.left(AppError.networkError(e.message));
}
}
}
// fold के साथ उपयोग
final result = await service.fetchUser('42');
result.fold(
(left) => showError(left.message),
(right) => showUser(right),
);
Either<L, R> fpdart से वाम-पक्षीय प्रकार है: Left — त्रुटि, Right — सफलता। fetchUser Either<AppError, User> लौटाता है, जहाँ AppError ठोस त्रुटि प्रकारों (serverError, networkError) वाली एक सील्ड क्लास है। fold दोनों मामलों को संभालता है: पहला कॉलबैक Left (त्रुटि) के लिए, दूसरा Right (सफलता) के लिए। Dart 3.0 में, अंतर्निर्मित Result भी fold का समर्थन करता है, लेकिन map/flatMap प्रदान नहीं करता है। श्रृंखलाओं के लिए, fpdart से Either map, flatMap (bind), mapLeft, andThen प्रदान करता है — त्रुटि संयोजन के लिए कार्यात्मक संयोजकों का एक पूर्ण सेट।
एक्सेप्शन पर Result का मुख्य लाभ संयोजन है। यदि आपके पास कई संचालन हैं, जिनमें से प्रत्येक विफल हो सकता है, तो आप बिना एक नेस्टेड if या try-catch के map और flatMap का उपयोग करके उन्हें श्रृंखलाबद्ध कर सकते हैं। map सफलता मान को रूपांतरित करता है: Result.success(x) -> Result.success(f(x)). flatMap (जिसे bind या andThen भी कहा जाता है) उन मामलों के लिए है जहाँ रूपांतरण स्वयं Result लौटाता है: Result.success(x) -> f(x) -> Result<Y>. यदि कोई भी चरण Failure के साथ विफल होता है, तो बाद के संचालन निष्पादित नहीं होते हैं — श्रृंखला बाधित हो जाती है।
data class UserRequest(val userId: String, val token: String)
sealed class AuthError {
data object InvalidToken : AuthError()
data class UserNotFound(val id: String) : AuthError()
}
typealias Outcome<T> = Either<AuthError, T>
fun validateToken(token: String): Outcome<String> =
if (token.isNotBlank()) Either.right(token)
else Either.left(AuthError.InvalidToken)
fun fetchProfile(userId: String): Outcome<Profile> =
if (userId == "42") Either.right(Profile("Alice"))
else Either.left(AuthError.UserNotFound(userId))
// flatMap के माध्यम से संयोजन (fpdart में andThen)
val result = validateToken("abc123")
.flatMap { fetchProfile("42") }
.map { it.name }
.getOrElse { "Guest" }
println(result) // "Alice"
श्रृंखला: validateToken -> fetchProfile -> map name -> getOrElse “अतिथि”. यदि validateToken Left (InvalidToken) लौटाता है, तो श्रृंखला बाधित होती है और “अतिथि” लौटाती है। यदि fetchProfile Left (UserNotFound) लौटाता है — भी “अतिथि”. यदि दोनों संचालन सफल होते हैं — प्रोफ़ाइल नाम. flatMap Either फ़ंक्शन को संयोजित करने की अनुमति देता है, जिनमें से प्रत्येक विफल हो सकता है, एक रैखिक श्रृंखला में। पारंपरिक एक्सेप्शन शैली में, समान कोड के लिए दो नेस्टेड try-catch या null जाँच की आवश्यकता होगी। अंत में getOrElse संयोजन से बाहर निकलने का बिंदु है, जो Failure मामले के लिए डिफ़ॉल्ट मान प्रदान करता है।
Result और एक्सेप्शन परस्पर अनन्य दृष्टिकोण नहीं हैं। प्रत्येक का अपना डोमेन है, और एक अच्छी तरह से डिज़ाइन किए गए मोबाइल एप्लिकेशन में, दोनों का उपयोग किया जाता है। चुनाव इस बात पर निर्भर करता है कि त्रुटि अपेक्षित है या अप्रत्याशित। Result अपेक्षित त्रुटियों के लिए है जो व्यावसायिक तर्क का हिस्सा हैं: अमान्य ईमेल, अपर्याप्त धन, दर सीमा पार हो गई। एक्सेप्शन अप्रत्याशित सिस्टम त्रुटियों के लिए हैं: नेटवर्क हानि, OutOfMemoryError, NullPointerException (जो नहीं होनी चाहिए लेकिन होती हैं).
| मानदंड | Result Type | एक्सेप्शन (Exception/Error) |
|---|---|---|
| त्रुटि प्रकार | अपेक्षित (व्यावसायिक तर्क) | अप्रत्याशित (सिस्टम) |
| प्रदर्शन | कम लागत (बिना स्टैक अनवाइंडिंग) | उच्च लागत (स्टैक अनवाइंडिंग, StackTrace कैप्चर) |
| संयोजन | map/flatMap के माध्यम से — रैखिक श्रृंखलाएँ | नेस्टेड try-catch — पढ़ने में कठिन |
| कंपाइलर | व्यापक जाँच (switch/when) | केवल Java में चेक किए गए एक्सेप्शन |
| निष्पादन प्रवाह | बाधित नहीं होता — त्रुटि एक मान के रूप में | निकटतम catch तक बाधित होता है |
| परीक्षण | आसान: परिणाम जाँचें, isSuccess/isError की पुष्टि करें | assertThrows और मॉक ऑब्जेक्ट की आवश्यकता है |
| कब उपयोग करें | व्यावसायिक सत्यापन, अनुरोध श्रृंखलाएँ, फ़ॉर्म | नेटवर्क हानि, I/O त्रुटियाँ, सिस्टम क्रैश |
व्यावहारिक नियम: यदि त्रुटि सामान्य एप्लिकेशन वर्कफ़्लो का हिस्सा है (उपयोगकर्ता ने अमान्य ईमेल दर्ज किया, अपर्याप्त अनुमतियाँ) — Result का उपयोग करें। यदि त्रुटि एक असाधारण स्थिति है (सर्वर प्रतिक्रिया नहीं दे रहा, मेमोरी खत्म) — एक्सेप्शन का उपयोग करें। मोबाइल डेवलपमेंट में, परत सीमाओं पर Result (UseCase -> ViewModel) और परतों के भीतर एक्सेप्शन (API -> Repository) एक सामान्य पैटर्न है जो दोनों दृष्टिकोणों के लाभों को जोड़ता है।
मौजूदा एक्सेप्शन-आधारित कोड का Result में माइग्रेशन क्रमिक होना चाहिए। परत सीमाओं से शुरू करें: throws फ़ंक्शन कॉल को Result { try ... } (Swift) या runCatching { ... } (Kotlin) में लपेटें। फिर Repository और UseCase विधियों के रिटर्न प्रकार को Result/Either से बदलें, आंतरिक कार्यान्वयन को एक्सेप्शन पर रखते हुए। अंतिम चरण में, ViewModel को माइग्रेट करें: एक्सेप्शन वाले UiState के बजाय, एक सील्ड क्लास UiState<T> (Loading, Success, Error) का उपयोग करें, जहाँ Error एक Throwable नहीं बल्कि एक डोमेन त्रुटि संग्रहीत करता है। क्रमिक माइग्रेशन वैश्विक रिफैक्टरिंग के बिना प्रत्येक परत का अलग-अलग परीक्षण करने की अनुमति देता है।
अक्सर पूछे जाने वाले प्रश्न
Optional (T?) मान की उपस्थिति या अनुपस्थिति दर्शाता है — nil का अर्थ है “कोई डेटा नहीं” लेकिन यह कारण नहीं बताता। Result (Success/Failure) में न केवल सफलता बल्कि एक ठोस प्रकार के साथ त्रुटि का कारण भी शामिल है। Optional का उपयोग करें जब अनुपस्थिति सामान्य हो (उदाहरण के लिए, एक वैकल्पिक प्रोफ़ाइल फ़ील्ड), और Result का उपयोग करें जब आपको त्रुटि जानकारी की आवश्यकता हो।
Swift में, Result { try throwingFunc() } का उपयोग करें — Result कंस्ट्रक्टर एक थ्रोइंग क्लोज़र लेता है। Kotlin में, runCatching { throwingFunc() } का उपयोग करें, जो Result<T> लौटाता है। Dart में, Result<T>.tryCatch(() => throwingFunc()) का उपयोग करें। यह Result श्रृंखलाओं में एक्सेप्शन-आधारित कोड के आसान एकीकरण की अनुमति देता है।
सफलता मान को बदले बिना त्रुटि प्रकार को रूपांतरित करने के लिए mapError (Swift) या mapLeft (Dart/Kotlin में Either) का उपयोग करें। यदि आपको दोनों मामलों को संभालने और एक एकल मान लौटाने की आवश्यकता है, तो fold का उपयोग करें। श्रृंखला को बाधित किए बिना लॉगिंग के लिए, onFailure (Kotlin) या एक उपसर्ग निरीक्षण बिंदु का उपयोग करें।
हाँ, लेकिन सावधानी से। K2 कंपाइलर और रिफ्लेक्शन विशेषताओं के कारण Kotlin Result<T> को सीधे suspend फ़ंक्शन के रिटर्न प्रकार के रूप में अनुशंसित नहीं किया जाता है। कोरूटीन में स्थितियों का प्रतिनिधित्व करने के लिए अपनी स्वयं की सील्ड क्लास NetworkResult<T> (Success, Error, Loading) का उपयोग करें। व्यावसायिक तर्क में अपेक्षित त्रुटियों के लिए, Arrow से Either एक अधिक शक्तिशाली विकल्प है।
fold एक विधि है जो दो कॉलबैक लेती है: onSuccess (सफलता मामले के लिए) और onFailure (त्रुटि मामले के लिए), और किसी भी प्रकार का एक एकल मान लौटाती है। यह switch अभिव्यक्ति के समतुल्य है लेकिन उच्च-क्रम फ़ंक्शन के रूप में। fold Result श्रृंखलाओं से मुख्य निकास बिंदु है, जहाँ आप Success/Failure को UiState, उपयोगकर्ता-सामना वाली स्ट्रिंग या किसी अन्य Result में परिवर्तित करते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें