Either: ماهیت، کاربرد و اصل عملکرد

نویسنده: IT Sectr منتشر شده: 2026-05-26 زمان مطالعه: 8 دقیقه

Either — نوع تابعی است که مقدار یکی از دو گزینه ممکن را نشان می‌دهد: چپ (Left) برای خطا و راست (Right) برای موفقیت. برخلاف استثناها، Either مدیریت خطا را در سطح نوع صریح می‌کند و به بلوک‌های try-catch نیاز ندارد. طبق داده‌های Arrow, 2026، Either به طور گسترده در پروژه‌های Kotlin برای ترکیب عملیاتی که ممکن است شکست بخورند، بدون عوارض جانبی استفاده می‌شود.

نکات اصلی

  • Either — نوع داده جبری برای نمایش دو گزینه متقابل انحصاری: Left (خطا) و Right (موفقیت).
  • Left به طور سنتی حاوی اطلاعات خطا است، Right — مقدار صحیح.
  • نوع‌بندی صریح — Either پردازش هر دو گزینه را در مرحله کامپایل الزامی می‌کند و خرابی‌های غیرمنتظره را حذف می‌کند.
  • ترکیب — Either از map، flatMap و fold برای زنجیره‌های تبدیل بدون بررسی‌های تودرتو پشتیبانی می‌کند.
  • تفاوت با Result — Either می‌تواند نوع خطای دلخواه را ذخیره کند، نه فقط Error یا Throwable.

Either چیست؟

Either — یک نوع داده جبری برگرفته از برنامه‌نویسی تابعی است که مقدار دقیقاً یکی از دو نوع ممکن را نشان می‌دهد. در زمینه مدیریت خطا، قرارداد زیر پذیرفته شده است: نوع چپ (Left) حاوی شرح مشکل است و راست (Right) — نتیجه موفق.

مفهوم Either به زبان Haskell و دسته انواع Either a b برمی‌گردد، جایی که a نوع مقدار چپ و b نوع مقدار راست است. در توسعه موبایل، Either به لطف کتابخانه Arrow برای Kotlin و رویکردهای تابعی در Swift محبوبیت یافته است.

مزیت کلیدی Either نسبت به استثناها — عدم وجود مسیرهای اجرای پنهان است. تابعی که Either برمی‌گرداند به صراحت در امضای خود اعلام می‌کند که ممکن است با خطا پایان یابد. کامپایلر بررسی می‌کند که آیا هر دو گزینه پردازش شده‌اند.

برخلاف پرتاب استثناها، Either شفافیت جریان داده را حفظ می‌کند. فراخوانی تابعی که Either برمی‌گرداند به try-catch در سمت کد فراخوان نیاز ندارد — pattern-matching یا fold کافی است. این امر به ویژه در معماری‌هایی با رویکرد واکنشی مهم است، جایی که هر منبع داده Either برمی‌گرداند و زنجیره تبدیل از طریق map و flatMap ساخته می‌شود.

Either چگونه کار می‌کند: ساختار Left و Right

Either از دو زیرنوع تشکیل شده است: Left و Right. یک نمونه Either در هر لحظه فقط می‌تواند یکی از آنها باشد. امضای معمول در Kotlin به صورت Either<E, A> است، جایی که E نوع خطا و A نوع مقدار موفق است.

نوع Left: ظرف خطا

Left حالت خرابی را نشان می‌دهد. برخلاف استثناها، Left جریان اجرا را قطع نمی‌کند — فقط مقداری را برمی‌گرداند که باید پردازش شود. نوع خطا می‌تواند هر چیزی باشد: String، Int، sealed class سفارشی یا مدل دامنه.

نوع Right: ظرف موفقیت

Right حاوی نتیجه صحیح عملیات است. نام نشان‌دهنده «صحت» است — طبق قرارداد Right به معنای موفقیت است. تبدیل‌های map و flatMap روی Right اعمال می‌شوند که این امکان را می‌دهد زنجیره‌های محاسباتی بدون بررسی هر مرحله ساخته شوند.

ترکیب Either از طریق flatMap

flatMap — مکانیزم اصلی ترکیب Either است. اگر مقدار فعلی Right باشد، flatMap تابع ارسال شده را اعمال می‌کند و Either جدیدی برمی‌گرداند. اگر Left باشد — flatMap تبدیل را رد می‌کند و خطا را به جلو منتقل می‌کند. این رفتار short-circuit evaluation نامیده می‌شود.

علاوه بر flatMap، Either از mapLeft برای تبدیل خطا، fold برای پردازش هر دو گزینه در یک مکان و getOrElse برای استخراج مقدار با پیش‌فرض پشتیبانی می‌کند. این توابع همه سناریوها را پوشش می‌دهند: از استخراج ساده تا ترکیب پیچیده با فراخوانی‌های ناهمگام در کوروتین‌های Kotlin یا Combine در Swift.

kotlin
fun parseInt(input: String): Either<String, Int> =
    input.toIntOrNull()?.let { Right(it) }
    ?: Left("امکان تبدیل وجود ندارد: $input")

fun divide(a: Int, b: Int): Either<String, Int> =
    if (b == 0) Left("تقسیم بر صفر")
    else Right(a / b)

val result = parseInt("10")
    .flatMap { divide(it, 2) }

Either در Kotlin: کاربرد عملی

در اکوسیستم Kotlin Either در کتابخانه Arrow پیاده‌سازی شده است. کتابخانه استاندارد Kotlin Result را ارائه می‌دهد، اما Either انعطاف‌پذیری بیشتری می‌دهد: نوع خطای دلخواه، ترکیب از طریق flatMap و پشتیبانی از الگوهای تابعی.

کتابخانه Arrow و Either

Arrow — کتابخانه تابعی برای Kotlin که Either، Option، Validated و انواع دیگر را اضافه می‌کند. Arrow.Either — sealed class با دو وراث: ArrowCore.Left و ArrowCore.Right. کتابخانه همچنین افزونه‌هایی برای کار راحت فراهم می‌کند: .getOrElse()، .fold()، .mapLeft().

مثال: Either با درخواست شبکه

یک سناریوی واقعی را در نظر بگیریم — درخواست شبکه در برنامه Android با خطاهای احتمالی: عدم وجود شبکه، خطای سرور، پاسخ نادرست. Either به شما امکان می‌دهد همه گزینه‌ها را در یک نوع بازگشتی ترکیب کنید.

kotlin
sealed class NetworkError {
    data class NoConnection(val message: String): NetworkError()
    data class ServerError(val code: Int): NetworkError()
    data class ParseError(val detail: String): NetworkError()
}

suspend fun fetchUser(id: String): Either<NetworkError, User> {
    return try {
        val response = api.getUser(id)
        if (response.isSuccessful) {
            Right(response.body()!!)
        } else {
            Left(NetworkError.ServerError(response.code()))
        }
    } catch (e: IOException) {
        Left(NetworkError.NoConnection(e.message ?: ""))
    }
}

Either در Swift: تفاوت با Result استاندارد

در Swift از نسخه 5.0 نوع داخلی Result ظاهر شده است که از نظر مفهومی شبیه Either است اما محدودیت‌هایی دارد: خطا باید با پروتکل Error مطابقت داشته باشد و مقدار موفق — یک نوع. Either در Swift از طریق enum با دو پارامتر جنریک پیاده‌سازی می‌شود.

Result استاندارد در مقابل Either

Result<Success, Failure> — نوع داخلی Swift که در آن Failure: Error. Either محدودیتی بر نوع خطا اعمال نمی‌کند که این امکان را می‌دهد String، ساختارهای سفارشی یا حتی چند نوع خطا را از طریق enum‌های تودرتو ذخیره کنید.

swift
enum Either<E, A> {
    case left(E)
    case right(A)

    func map<B>(_ transform: (A) -> B) -> Either<E, B> {
        switch self {
        case .left(let e): return .left(e)
        case .right(let a): return .right(transform(a))
        }
    }
}

let result: Either<String, Int> = .right(42)
let mapped = result.map { $0 * 2 }

چه زمانی از Either در برنامه‌های موبایل استفاده کنیم

Either برای سناریوهایی که نیاز به مدیریت خطای صریح و نوع‌امن بدون استثنا دارند بهینه است. موارد اصلی استفاده در توسعه موبایل با Kotlin و Swift را بررسی می‌کنیم.

  • درخواست‌های شبکه — هر درخواست ممکن است خطای اتصال، سرور یا تجزیه را برگرداند. Either همه گزینه‌ها را در یک نوع جمع می‌کند.
  • اعتبارسنجی فرم‌ها — Either با نوع خطای سفارشی به راحتی نتیجه بررسی فیلدهای ورودی را نشان می‌دهد: ایمیل یا رمز عبور نامعتبر.
  • مخزن داده — Either به شما امکان می‌دهد نتیجه را از منابع مختلف (کش، پایگاه داده، شبکه) با یک نوع خطای واحد ترکیب کنید.
  • مفسر دستورات — اگر برنامه ورودی کاربر یا دستورات را تجزیه می‌کند، Either راهی نوع‌امن برای گزارش خطا فراهم می‌کند.

از Either برای عملیات ساده بدون عوارض جانبی استفاده نکنید — مقدار بازگشتی معمولی قابل اعتمادتر و خواناتر است. Either همچنین زمانی که خرابی یک موقعیت استثنایی است نه یک سناریوی مورد انتظار، اضافی است.

Either همچنین هنگام کار با کوروتین‌ها در Kotlin مؤثر است. تابعی که Either برمی‌گرداند می‌تواند در داخل کوروتین با مدیریت خطا از طریق fold یا mapLeft بدون مسدود کردن رشته فراخوانی شود. این امر به ویژه در برنامه‌های Android با معماری MVVM مفید است، جایی که هر مخزن Either برمی‌گرداند و ViewModel نتیجه را به UiState تبدیل می‌کند.

اشتباهات رایج هنگام کار با Either

توسعه‌دهندگانی که برای اولین بار با Either آشنا می‌شوند اغلب اشتباهات مشابهی مرتکب می‌شوند. رایج‌ترین آنها و راه‌های اجتناب را بررسی می‌کنیم.

  • نادیده گرفتن Left — فراخوانی .getOrElse() با مقدار پیش‌فرض بدون تحلیل دلیل خطا، استفاده از Either را بی‌معنی می‌کند. خطا را به صراحت مدیریت کنید.
  • نوع خطای سراسری — استفاده از String یا Exception به عنوان نوع مشترک برای همه Either‌ها در پروژه امنیت نوع را کاهش می‌دهد. sealed class‌های دامنه ایجاد کنید.
  • Either‌های تودرتو — Either تکراری داخل Right (Either<E, Either<E, A>>) خواندن را دشوار می‌کند. برای صاف‌سازی از flatMap استفاده کنید.
  • مخلوط کردن با استثناها — تابع Either برمی‌گرداند اما در داخل استثنا پرتاب می‌کند. این با ایده مدیریت صریح خطا در تضاد است.

سوالات متداول

Either چه تفاوتی با Optional دارد؟

Optional وجود یا عدم وجود مقدار (Some/None) را نشان می‌دهد اما دلیل عدم وجود را بیان نمی‌کند. Either دو نوع مشخص می‌دهد — چپ برای خطا و راست برای موفقیت، که امکان انتقال زمینه خرابی را فراهم می‌کند.

آیا می‌توان از Either در Java استفاده کرد؟

در Java Either داخلی وجود ندارد، اما کتابخانه‌های Vavr و functionaljava پیاده‌سازی را ارائه می‌دهند. در توسعه Android، Either از Vavr یک جایگزین محبوب برای سبک تابعی با لامبداها است.

چه زمانی به جای Either از sealed class استفاده کنیم؟

Sealed class در Kotlin زمانی راحت‌تر است که گزینه‌ها بیش از دو تا باشند یا ساختار متفاوتی داشته باشند. برای نتیجه باینری (خطا/موفقیت) Either فشرده‌تر است و ترکیب‌کننده‌های تابعی آماده ارائه می‌دهد.

آیا Either از چندنخی پشتیبانی می‌کند؟

Either غیرقابل تغییر و به طور پیش‌فرض ایمن از نظر نخ است. در Kotlin با کوروتین‌ها Either به خوبی ترکیب می‌شود: flatMap در داخل coroutine scope کار می‌کند و مدیریت خطا نیازی به قفل ندارد.

آیا ارزش استفاده از Either برای همه توابع در پروژه را دارد؟

خیر. Either برای عملیات با خرابی‌های مورد انتظار (شبکه، اعتبارسنجی، منطق کسب‌وکار) مناسب است. برای getterهای ساده و محاسبات بدون عوارض جانبی، نوع معمولی خواناتر است و پیچیدگی اضافی ایجاد نمی‌کند.

خلاصه

  • Either — نوع تابعی برای نمایش دو گزینه: Left (خطا) و Right (موفقیت)، که مدیریت خرابی را در سطح نوع صریح می‌کند.
  • Left می‌تواند برخلاف Result استاندارد، هر نوع خطایی را شامل شود — از String تا sealed class دامنه.
  • flatMap ترکیب Either را بدون بررسی‌های تودرتو فراهم می‌کند: خطا به طور خودکار از کل زنجیره عبور می‌کند.
  • Arrow — کتابخانه اصلی Either برای Kotlin با پشتیبانی داخلی از کوروتین‌ها و افزونه‌ها.
  • Swift از Result داخلی استفاده می‌کند، اما Either برای انعطاف‌پذیری کامل از طریق enum با دو پارامتر جنریک پیاده‌سازی می‌شود.
  • Either را برای درخواست‌های شبکه، اعتبارسنجی فرم‌ها و مخازن — سناریوهای دارای خطاهای مورد انتظار — به کار ببرید.
  • از نوع خطای سراسری، نادیده گرفتن Left و Either‌های تودرتو خودداری کنید — این مزایای امنیت نوع را کاهش می‌دهد.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید