لامبدا: چیست، نحو و استفاده در Kotlin

نویسنده: IT Sectr منتشر شده: 2026-06-23 زمان مطالعه: 7 دقیقه

لامبدا — یک تابع ناشناس است که به صورت یک عبارت فشرده { آرگومان‌ها -> بدنه } ارائه می‌شود. در Kotlin، لامبداها روش اصلی انتقال رفتار به توابع مرتبه بالا (higher-order functions) هستند و نحوی مختصر بدون نیاز به اعلام یک تابع جداگانه فراهم می‌کنند. طبق مستندات Kotlin (2026)، بیش از 70% توابع مرتبه بالا در پروژه‌های معمولی با لامبدا فراخوانی می‌شوند. لامبدا امکان نوشتن کد به سبک تابعی با حداقل نویز نحوی را فراهم می‌کند.

نکات اصلی

  • لامبدا — تابع ناشناس در نحو { args -> body } بدون نام
  • نام ضمنی it تنها آرگومان لامبدا را جایگزین کرده و نوشتن را ساده می‌کند
  • Trailing lambda — خارج کردن آخرین لامبدا از پرانتز فراخوانی برای خوانایی
  • تصاحب (closure) — لامبدا می‌تواند به متغیرهای حوزه دید خارجی دسترسی داشته باشد
  • نوع تابعی (T) -> R امضای لامبدا را تعیین کرده و توسط کامپایلر بررسی می‌شود

لامبدا چیست؟

لامبدا (عبارت لامبدا) — یک تابع ناشناس است که به صورت عبارت تعریف می‌شود، نه اعلام. این اصطلاح از حساب لامبدای آلونزو چرچ (1936) گرفته شده است. در برنامه‌نویسی، لامبدا یک بلوک کد را نشان می‌دهد که می‌تواند به عنوان مقدار منتقل شود، در متغیر ذخیره گردد و بعداً فراخوانی شود. در Kotlin، لامبدا همیشه در آکولاد { } قرار می‌گیرد، آرگومان‌ها با فلش -> از بدنه جدا می‌شوند.

لامبدا با یک تابع معمولی در نداشتن نام و کلمه کلیدی fun متفاوت است. این امکان را می‌دهد که رفتار را مستقیماً در نقطه استفاده اعلام کرد، بدون اینکه کد را با اعلام‌های اضافی شلوغ کند. کامپایلر Kotlin انواع آرگومان‌ها را از زمینه استخراج می‌کند، بنابراین در بسیاری از موارد می‌توان انواع را حذف کرد. لامبدا شکر نحوی بر روی نوع تابعی (T) -> R است: هر لامبدا یک نوع تابعی متناظر دارد.

کاربرد اصلی لامبداها در Kotlin انتقال به توابع مرتبه بالا (higher-order functions) است. کتابخانه استاندارد در همه جا از لامبدا استفاده می‌کند: filter { it > 0 }، map { it.uppercase() }، forEach { println(it) }. لامبداها همچنین برای ایجاد شنوندگان رویداد، callbackها، پیکربندی‌کننده‌های اشیاء از طریق apply و run استفاده می‌شوند که کد را در مقایسه با کلاس‌های ناشناس اعلامی‌تر می‌کند.

نحو عبارات لامبدا در Kotlin

شکل کامل عبارت لامبدا در Kotlin: { آرگومان‌ها -> بدنه_لامبدا }. آرگومان‌ها با کاما فهرست می‌شوند، سپس فلش و بدنه — یک یا چند عبارت. اگر بدنه شامل چند خط باشد، آخرین عبارت مقدار بازگشتی می‌شود. اگر تابع لامبدا را به عنوان آخرین آرگومان بپذیرد، می‌توان آن را خارج از پرانتز فراخوانی قرار داد.

kotlin
val sum: (Int, Int) -> Int = { a, b -> a + b }

// انواع استخراج شده از زمینه
val sumShort = { a: Int, b: Int -> a + b }

// فراخوانی لامبدا
val result = sum(5, 3)  // 8
println(result)

متغیر sum با نوع تابعی صریح (Int, Int) -> Int اعلام شده و با لامبدای { a, b -> a + b } مقداردهی شده است. برای sumShort انواع داخل لامبدا مشخص شده و نوع متغیر استخراج شده است. هر دو معادل هستند. فراخوانی لامبدا هیچ تفاوتی با فراخوانی تابع معمولی ندارد — از نحو sum(5, 3) استفاده می‌شود. لامبدای بدون آرگومان به صورت { body }، با یک آرگومان — { it -> it * 2 } یا صرفاً { it * 2 } نوشته می‌شود.

نام ضمنی it و حذف آرگومان‌ها

وقتی لامبدا دقیقاً یک آرگومان می‌پذیرد، Kotlin نام ضمنی it را فراهم می‌کند. این کار نیاز به اعلام آرگومان در سمت چپ را از بین می‌برد. برنامه‌نویس فقط بدنه لامبدا را می‌نویسد و از it برای دسترسی به تنها پارامتر استفاده می‌کند. چنین نحوی به ویژه در زنجیره‌های پردازش مجموعه‌ها راحت است، جایی که it عنصر جاری را نشان می‌دهد.

kotlin
val numbers = listOf(1, 2, 3, 4, 5)

// نام پارامتر صریح
val squaredExplicit = numbers.map { n -> n * n }

// it ضمنی
val squared = numbers.map { it * it }

// فیلتر کردن با it
val even = numbers.filter { it % 2 == 0 }

println(squared) // [1, 4, 9, 16, 25]

در مثال map { it * it } از it به جای اعلام n -> استفاده شده است. Kotlin به طور خودکار it را برای تنها پارامتر لامبدا تعیین می‌کند. اگر لامبدا دو یا بیشتر آرگومان بپذیرد، it ایجاد نمی‌شود — باید همه پارامترها را صریحاً اعلام کرد. برای خوانایی بهتر لامبداهای تودرتو، بهتر است به پارامترها نام‌های معنادار داده و it را در محمول‌های کوتاه یک خطی استفاده کرد.

Trailing lambda و لامبداهای چندخطی

Trailing lambda (لامبدای پایانی) — ویژگی نحوی Kotlin که اجازه می‌دهد آخرین آرگومان-لامبدا را خارج از پرانتز گرد فراخوانی تابع قرار دهیم. این کار کد را شبیه به ساختارهای زبانی توکار می‌کند. اگر لامبدا تنها آرگومان باشد، پرانتزها را می‌توان کاملاً حذف کرد. این رویکرد به طور فعال در کتابخانه استاندارد و DSL استفاده می‌شود.

kotlin
// فراخوانی استاندارد
thread(block = {
    println("سلام از رشته")
})

// نسخه trailing lambda
thread {
    println("سلام از رشته")
}

// repeat با trailing lambda
repeat(3) { index ->
    println("تکرار $index")
}

// run با لامبدای چندخطی
val config = run {
    val host = "localhost"
    val port = 8080
    "$host:$port"
}

تابع thread Runnable را به عنوان آخرین آرگومان می‌پذیرد. به لطف trailing lambda می‌توان لامبدا را خارج از پرانتز منتقل کرد که از نظر بصری شبیه بلوک کد است. تابع repeat تعداد تکرارها و لامبدا با ایندکس را می‌پذیرد. run — نمونه‌ای از تابع مرتبه بالا است که در آن لامبدای چندخطی مقداری را که توسط آخرین عبارت بازگردانده می‌شود محاسبه می‌کند. پرانتزهای اطراف run() را می‌توان حذف کرد اگر لامبدا تنها آرگومان باشد.

تصاحب متغیرها (closure) در لامبداها

تصاحب متغیرها (closure) — توانایی لامبدا برای دسترسی به متغیرهای اعلام شده در حوزه دید خارجی. در Kotlin، لامبدا می‌تواند متغیرهای var را بخواند و تغییر دهد، همچنین متغیرهای val را از زمینه اطراف بخواند. متغیرهای تصاحب شده در طول چرخه حیات لامبدا همراه با آن ذخیره می‌شوند که امکان ایجاد توابع با حالت را فراهم می‌کند.

kotlin
fun makeCounter(): () -> Int {
    var count = 0
    return {
        count++  // تعداد تصاحب‌ها
    }
}

fun main() {
    val counter = makeCounter()
    println(counter()) // 0
    println(counter()) // 1
    println(counter()) // 2
}

تابع makeCounter یک متغیر محلی count را اعلام کرده و لامبدای { count++ } را برمی‌گرداند. با وجود اینکه makeCounter کار خود را تمام کرده، لامبدای برگشتی از طریق بستار (closure) ارجاع به count را نگه می‌دارد. هر بار فراخوانی counter() مقدار جاری را افزایش داده و برمی‌گرداند. مکانیزم closure اساس کاری‌کردن، کارخانه‌های تابع و به‌خاطرسپاری را تشکیل می‌دهد. مهم است به خاطر داشت که تصاحب متغیرهای قابل تغییر ممکن است در اجرای همزمان منجر به رفتار غیرمنتظره شود.

پرسش‌های متداول

آیا لامبدا می‌تواند return داشته باشد؟

لامبدا return بدون قید را پشتیبانی نمی‌کند — return بدون برچسب کنترل را به تابع خارجی برمی‌گرداند. برای خروج از لامبدا از return@label استفاده کنید، جایی که label نام تابع مرتبه بالایی است که لامبدا به آن منتقل شده است.

تفاوت بین لامبدا و تابع ناشناس چیست؟

تابع ناشناس به صورت fun(a: Int): Int { return a * 2 } نوشته می‌شود و return بدون برچسب را پشتیبانی می‌کند. لامبدا { a -> a * 2 } از نظر نحوی کوتاه‌تر است اما برای خروج زودهنگام نیاز به return@label دارد.

چگونه لامبدا را بدون فلش به عنوان آرگومان منتقل کنیم؟

اگر لامبدا آرگومانی نمی‌پذیرد، فلش حذف می‌شود: { body() }. اگر یک آرگومان می‌پذیرد و از آن استفاده نمی‌کند، به جای فلش { _ -> body() } با زیرخط برای نادیده گرفتن پارامتر نوشته می‌شود.

آیا لامبدا همیشه یک شیء جدید ایجاد می‌کند؟

بله، هر لامبدایی که به تابع non-inline منتقل می‌شود، یک نمونه از کلاس ناشناس ایجاد می‌کند. برای توابع inline، لامبدا بدون ایجاد شیء در محل فراخوانی جایگذاری می‌شود. لامبداهای non-capturing در اشیاء singleton کش می‌شوند.

چرا در لامبدا نمی‌توان مستقیماً از return استفاده کرد؟

Return در Kotlin یک عملگر انتقال است که به نزدیک‌ترین تابع با fun تعلق دارد. لامبدا یک تابع (fun) نیست، بلکه یک عبارت است. بنابراین return داخل لامبدا بدون برچسب به عنوان بازگشت از تابع خارجی محصورکننده در نظر گرفته می‌شود.

خلاصه

  • لامبدا — تابع ناشناس در نحو { args -> body } که به عنوان مقدار به تابع مرتبه بالا منتقل می‌شود
  • نام ضمنی it تنها آرگومان را جایگزین کرده و کد را در محمول‌های کوتاه فشرده‌تر می‌کند
  • Trailing lambda آخرین لامبدا را برای خواندن به عنوان بلوک کد از پرانتز فراخوانی خارج می‌کند
  • تصاحب (closure) به لامبدا اجازه می‌دهد پس از پایان تابع محصورکننده به متغیرهای زمینه خارجی دسترسی داشته باشد
  • نوع تابعی (T) -> R امضای لامبدا را با بررسی در مرحله کامپایل تعیین می‌کند
  • توابع inline ایجاد کلاس‌های ناشناس برای لامبداها را حذف کرده و عملکرد را در حلقه‌ها افزایش می‌دهند
  • لامبداهای چندخطی مقدار آخرین عبارت را بازمی‌گردانند و محاسبات پیچیده را بدون اعلام تابع جداگانه پشتیبانی می‌کنند

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

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

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

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