Kotlin-এ ইনলাইন ফাংশন: এটি কী, সিনট্যাক্স এবং ব্যবহার

লেখক: IT Sectr প্রকাশিত: 2026-06-21 পড়ার সময়: 9 মিনিট

ইনলাইন ফাংশন — Kotlin মেকানিজম যেখানে ফাংশনের বডি কম্পাইল টাইমে সরাসরি প্রতিটি কল সাইটে প্রতিস্থাপিত হয়। এটি ল্যাম্বডা প্যারামিটারের জন্য অ্যানোনিমাস ক্লাস এবং অবজেক্ট তৈরির ওভারহেড দূর করে। Kotlin Documentation, 2025 অনুযায়ী, inline কীওয়ার্ড হায়ার-অর্ডার ফাংশনের জন্য বিশেষভাবে কার্যকর, যেখানে প্রতিটি ল্যাম্বডা ইনলাইনিং ছাড়া আলাদা FunctionN অবজেক্ট তৈরি করে, যা গার্বেজ কালেক্টরকে ভারী করে।

মূল পয়েন্ট

  • ইনলাইন ফাংশন — ফাংশন যার বডি কম্পাইল টাইমে কল সাইটে ইনলাইন করা হয়
  • ওভারহেড হ্রাস — ল্যাম্বডার জন্য অ্যানোনিমাস ক্লাস এবং অবজেক্ট তৈরি দূর করে
  • ননলোকাল রিটার্ন — ইনলাইন ফাংশনের ভিতরে ল্যাম্বডা বাইরের ফাংশন থেকে return করতে পারে
  • noinline — নির্দিষ্ট ল্যাম্বডা প্যারামিটারের ইনলাইনিং প্রতিরোধ করে
  • crossinline — ননলোকাল রিটার্ন অনুমতি দেয় কিন্তু ইনলাইন ফাংশন প্রসঙ্গ থেকে return নিষিদ্ধ করে

Kotlin-এ ইনলাইন ফাংশন কী?

ইনলাইন ফাংশন হল একটি ফাংশন যা inline কীওয়ার্ড দিয়ে চিহ্নিত। Kotlin কম্পাইলার এর জন্য আলাদা বাইটকোড তৈরি করে না — বরং ফাংশনের বডি সরাসরি প্রতিটি কল সাইটে কপি করে। মূল লক্ষ্য হল হায়ার-অর্ডার ফাংশন অপটিমাইজ করা যা ল্যাম্বডা এক্সপ্রেশন গ্রহণ করে, কারণ সাধারণ অবস্থায় প্রতিটি ল্যাম্বডা একটি অ্যানোনিমাস Function ক্লাস অবজেক্ট তৈরি করে।

JetBrains Tech Blog (2024) অনুযায়ী, Kotlin-এ ইনলাইন ফাংশন ব্যবহার করলে যে ফাংশনগুলো ল্যাম্বডা নিবিড়ভাবে ব্যবহার করে সেগুলোতে তৈরি অবজেক্টের সংখ্যা 40–60% কমানো যায়। লুপ এবং উচ্চ-লোড অপারেশনে (সর্টিং, কালেকশন ফিল্টারিং) এটি পরিমাপযোগ্য পারফরম্যান্স লাভ প্রদান করে।

Inline ছাড়া, প্রতিটি ল্যাম্বডা একটি অ্যানোনিমাস ক্লাসে (বা সংশ্লেষিত কার্যকরী ইন্টারফেসের ইনস্ট্যান্সে) কম্পাইল হয়। ভেরিয়েবল ক্যাপচার করা ল্যাম্বডার জন্য অতিরিক্ত র্যাপার অবজেক্ট তৈরি হয়। ইনলাইন ফাংশন কম্পাইল টাইমে এই সমস্ত অবজেক্ট দূর করে, র্যাপার ছাড়াই লোকাল ভেরিয়েবলে অ্যাক্সেস সহ সরাসরি কোড দিয়ে প্রতিস্থাপন করে।

শুধুমাত্র ল্যাম্বডা প্যারামিটারযুক্ত ফাংশনের জন্য inline ব্যবহার করুন — Kotlin কম্পাইলার নিজেই সতর্ক করে যদি inline কোনো সুবিধা না দেয়।

ইনলাইন ফাংশনের সিনট্যাক্স এবং এর কাজের পদ্ধতি

শুধু ফাংশন ডিক্লেয়ারেশনের আগে inline কীওয়ার্ড যোগ করুন। কম্পাইলার স্বয়ংক্রিয়ভাবে কল সাইটে ফাংশন বডি প্রতিস্থাপন করে। ফাংশনটি নিজে বাইটকোডে বিদ্যমান থাকে যখন এটি সরাসরি কল না করা হয় (উদাহরণস্বরূপ, Java কোড থেকে)।

kotlin
inline fun Int.repeatAction(action: (Int) -> Unit) {
    for (i in 0 until this) {
        action(i)
    }
}

// কল — ল্যাম্বডা কোড ফাংশন বডিতে ইনলাইন হয়
5.repeatAction { index ->
    println("Index: $index")
}

কম্পাইলেশনের পর, উপরের কোডটি এর সমতুল্য হবে:

kotlin
// ইনলাইনিংয়ের পরে কী হয় (পরিকল্পিতভাবে):
val $this = 5
for (i in 0 until $this) {
    println("Index: $i")
}

ল্যাম্বডার জন্য কোনো অবজেক্ট তৈরি হয় না — অ্যাকশন কোড সরাসরি এক্সিকিউট হয়। এটাই অপটিমাইজেশনের সারমর্ম: Function.invoke() কল করার পরিবর্তে — ল্যাম্বডা বডি সহ কোডের সরাসরি সন্নিবেশ।

ডিকম্পাইলেশনের মাধ্যমে যাচাই

ইনলাইনিং যাচাই করতে, IntelliJ IDEA-তে Tools > Kotlin > Show Kotlin Bytecode খুলুন এবং Decompile ক্লিক করুন। আপনি দেখতে পাবেন যে ল্যাম্বডা সহ repeatAction কল করার পরিবর্তে, for লুপ সহ ফাংশন বডির সরাসরি সন্নিবেশ তৈরি হয়।

ল্যাম্বডা ওভারহেডের সমস্যা এবং এর সমাধান

Kotlin-এ প্রতিটি ল্যাম্বডা তিনটি ভেরিয়েন্টের একটিতে কম্পাইল হয়। প্রথম — যদি ল্যাম্বডা ভেরিয়েবল ক্যাপচার না করে, তবে এটি সেই ক্লাসের একটি স্ট্যাটিক মেথড হয়ে যায় যেখানে ডিক্লেয়ার করা হয়েছে। দ্বিতীয় — যদি এটি একটি ভেরিয়েবল ক্যাপচার করে, একটি অ্যানোনিমাস ক্লাস তৈরি হয়। তৃতীয় — যদি এটি একাধিক ভেরিয়েবল ক্যাপচার করে, প্রতিটি ক্যাপচার করা ভেরিয়েবলের জন্য ফিল্ড সহ একটি অ্যানোনিমাস ক্লাস তৈরি হয়।

ল্যাম্বডার ধরনInline ছাড়াInline সহ
ক্যাপচার ছাড়াএকটি স্ট্যাটিক মেথড (পুনর্ব্যবহৃত)সম্পূর্ণ ইনলাইনিং, কল ছাড়া
1 ভেরিয়েবল ক্যাপচারঅ্যানোনিমাস ক্লাস (একটি অবজেক্ট)সম্পূর্ণ ইনলাইনিং, অবজেক্ট ছাড়া
N ভেরিয়েবল ক্যাপচারN ফিল্ড সহ অ্যানোনিমাস ক্লাসসম্পূর্ণ ইনলাইনিং, অবজেক্ট ছাড়া
পুনরাবৃত্তিমূলকসাধারণ কলinline নিষিদ্ধ

Android Performance Patterns (Google, 2024) অনুযায়ী, কালেকশনের নিবিড় ব্যবহার করা অ্যাপ্লিকেশনে (ফিল্টারিং, সর্টিং, গ্রুপিং) ইনলাইন ফাংশন অ্যালোকেশন 25–35% কমায়। প্রভাব বিশেষভাবে Jetpack Compose-এ লক্ষণীয়, যেখানে প্রতিটি স্টেট পরিবর্তন অনেক ল্যাম্বডা সহ পুনর্গঠন ট্রিগার করে।

ননলোকাল রিটার্ন এবং সীমাবদ্ধতা

সাধারণ ফাংশনে ল্যাম্বডা বাইরের ফাংশন থেকে return করতে পারে না — শুধুমাত্র ল্যাম্বডা থেকে লোকাল return (return@label এর মাধ্যমে)। ইনলাইন ফাংশনে, ল্যাম্বডা কলিং ফাংশনের বডিতে ইনলাইন হয়, তাই ননলোকাল রিটার্ন সম্ভব হয়: ল্যাম্বডার ভিতরে return বাইরের ফাংশন শেষ করে।

kotlin
inline fun findFirst(
    items: List<Int>,
    predicate: (Int) -> Boolean
): Int {
    for (item in items) {
        if (predicate(item)) {
            return item
        }
    }
    return -1
}

fun processNumbers() {
    val numbers = listOf(1, 2, 3)
    val firstEven = findFirst(numbers) { it % 2 == 0 }
    // ল্যাম্বডায় return processNumbers() থেকে null ফিরিয়ে দেবে
}

ননলোকাল রিটার্ন তাড়াতাড়ি শেষ করার জন্য সুবিধাজনক, কিন্তু ত্রুটির কারণ হতে পারে। যদি ল্যাম্বডা অ-লোকাল প্রসঙ্গে ব্যবহার করা হয় (একটি ভেরিয়েবলে সংরক্ষিত), ননলোকাল রিটার্ন RuntimeException ঘটাবে। Kotlin কম্পাইলার এই ধরনের সংরক্ষণের চেষ্টা করলে সতর্কতা জারি করে।

noinline এবং crossinline: ইনলাইনিং নিয়ন্ত্রণ

যখন একটি ফাংশনে একাধিক ল্যাম্বডা প্যারামিটার থাকে, কখনও কখনও শুধুমাত্র তাদের কিছু ইনলাইন করার প্রয়োজন হয়। এর জন্য noinline ব্যবহার করা হয় — এটি একটি নির্দিষ্ট ল্যাম্বডা প্যারামিটারের ইনলাইনিং প্রতিরোধ করে, এটিকে সাধারণ Function অবজেক্ট হিসেবে রেখে দেয়।

crossinline মডিফায়ার বিপরীত সমস্যা সমাধান করে: ল্যাম্বডা ইনলাইন হয়, কিন্তু ননলোকাল রিটার্ন নিষিদ্ধ। এটি প্রয়োজন যখন ল্যাম্বডা অন্য ল্যাম্বডার ভিতরে বা এমন প্রসঙ্গে ব্যবহার করা হয় যেখানে return অনুমোদিত নয় (উদাহরণস্বরূপ, Runnable-এ পাস করা)।

kotlin
inline fun processWithCallback(
    data: String,
    crossinline onSuccess: (String) -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        val result = process(data)
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

// noinline: onError একটি ভেরিয়েবলে সংরক্ষণ বা অন্যত্র পাস করা যেতে পারে
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)

উদাহরণে, onSuccess crossinline হিসেবে চিহ্নিত — এটি ইনলাইন হবে, কিন্তু এর ভিতরে return ব্যবহার করা যাবে না। onError noinline হিসেবে চিহ্নিত — এটি ইনলাইন হয় না, তাই এটি অবজেক্ট হিসেবে পাস করা, ক্লাস ফিল্ডে সংরক্ষণ বা লিসনার হিসেবে ব্যবহার করা যাবে।

ইনলাইন ফাংশনের সীমাবদ্ধতা এবং সুপারিশ

ইনলাইন ফাংশনের সীমাবদ্ধতা রয়েছে। পুনরাবৃত্তিমূলক ইনলাইন ফাংশন নিষিদ্ধ — কম্পাইলার ত্রুটি দেবে। ইনলাইন ফাংশনের private বা internal দৃশ্যমানতা থাকতে পারে না যদি অন্য মডিউলে ডিক্লেয়ার করা হয়, কিন্তু এটি দৃশ্যমানতার সীমাবদ্ধতা, ইনলাইনিং মেকানিজমের সাথে সম্পর্কিত নয়।

প্রতিটি ইনলাইন ফাংশন কলের সাথে বাইটকোড আকার বাড়ে, কারণ বডি কপি করা হয়। Kotlin Coding Conventions (JetBrains, 2025) অনুযায়ী, শুধুমাত্র 10–15 লাইন পর্যন্ত ফাংশনের জন্য inline ব্যবহার করার সুপারিশ করা হয়। বড় ফাংশনের জন্য, ল্যাম্বডা ইনলাইনিংয়ের সুবিধা APK আকার বৃদ্ধির কারণে নাকচ হয়ে যেতে পারে (Android-এ 64K মেথড সীমার কারণে গুরুত্বপূর্ণ)।

kotlin
// প্রস্তাবিত অনুশীলন
inline fun withLock(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    } finally {
        lock.unlock()
    }
}

// বড় ফাংশনের জন্য প্রস্তাবিত নয়
inline fun largeComputation(...) { // খারাপ — বডি >50 লাইন
    // 50 লাইনের বেশি — সাধারণ ফাংশনে আলাদা করা ভাল
}

লাইব্রেরিতে পাবলিক ইনলাইন ফাংশন সতর্কতা প্রয়োজন: যদি ইনলাইন ফাংশনের বডি পরিবর্তিত হয়, সমস্ত ক্লায়েন্টকে পুনরায় কম্পাইল করতে হবে। JetBrains একটি মডিউলের মধ্যে সামঞ্জস্য বজায় রাখতে ইনলাইন ফাংশন থেকে কল করা সদস্যদের জন্য @PublishedApi internal ব্যবহারের সুপারিশ করে।

সচরাচর জিজ্ঞাসিত প্রশ্ন

ইনলাইন এক্সটেনশন ফাংশন তৈরি করা যায় কি?

হ্যাঁ, ইনলাইন এক্সটেনশন ফাংশন কোনো সীমাবদ্ধতা ছাড়াই কাজ করে। উদাহরণ: inline fun String.transform(block: (Char) -> Char): String। এক্সটেনশন ইনলাইন করার ক্ষমতাকে প্রভাবিত করে না — কম্পাইলার এটিকে সাধারণ ইনলাইন ফাংশনের মতোই হ্যান্ডেল করে।

কখন inline কোনো সুবিধা দেয় না?

যদি ফাংশন ল্যাম্বডা প্যারামিটার গ্রহণ না করে — inline কোনো সুবিধা দেয় না। Kotlin কম্পাইলার সতর্কতা জারি করে: “Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types.” এছাড়াও, বাইটকোড বৃদ্ধির কারণে inline বড় ফাংশনের জন্য ক্ষতিকর।

inline কীভাবে @JvmInline (value class) থেকে আলাদা?

inline — একটি ফাংশন মডিফায়ার যা কল সাইটে ফাংশন বডি ইনলাইন করে। @JvmInline (value class) — র্যাপার ক্লাসের জন্য মেকানিজম যা কম্পাইল টাইমে তাদের মান দিয়ে প্রতিস্থাপিত হয়। ভিন্ন ধারণা: inline কল অপটিমাইজ করে, value class ডেটা উপস্থাপনা অপটিমাইজ করে।

suspend ফাংশনের সাথে inline ব্যবহার করা যায় কি?

না, suspend ফাংশন inline হতে পারে না কারণ তারা Continuation সহ স্টেট মেশিনে কম্পাইল হয়। তবে, একটি ইনলাইন ফাংশন crossinline সহ প্যারামিটার হিসেবে suspend ল্যাম্বডা গ্রহণ করতে পারে। এটি প্রায়শই করুটিনে ব্যবহৃত হয়: inline fun launch(block: suspend CoroutineScope.() -> Unit).

inline কি ডিবাগিং প্রভাবিত করে?

হ্যাঁ, ইনলাইন ফাংশন ডিবাগিং জটিল করে কারণ ফাংশন বডি কল না হয়ে কল সাইটে ইনলাইন হয়। স্ট্যাকট্রেস লম্বা হয়, ব্রেকপয়েন্ট কাজ করে কিন্তু অপ্রত্যাশিত অবস্থান দেখাতে পারে। JetBrains ইনলাইন ছাড়া ডিবাগ করার এবং শুধুমাত্র release বিল্ডে এটি সক্রিয় করার সুপারিশ করে।

সারসংক্ষেপ

  • ইনলাইন ফাংশন — ফাংশন বডি কল সাইটে ইনলাইন করে, ল্যাম্বডা ওভারহেড দূর করে
  • ননলোকাল রিটার্ন — ল্যাম্বডা থেকে return বাইরের ফাংশন শেষ করে (শুধুমাত্র inline-এ সম্ভব)
  • noinline — নির্দিষ্ট ল্যাম্বডা প্যারামিটারের ইনলাইনিং প্রতিরোধ করে
  • crossinline — ইনলাইনিং অনুমতি দেয় কিন্তু ননলোকাল রিটার্ন নিষিদ্ধ করে
  • পুনরাবৃত্তিমূলক ফাংশন inline হতে পারে না — কম্পাইলার ত্রুটি দেয়
  • বাইটকোড আকার বাড়ে — 10–15 লাইন পর্যন্ত ফাংশনের জন্য inline ব্যবহার করুন
  • অপটিমাল ব্যবহার — ল্যাম্বডা প্যারামিটারযুক্ত হায়ার-অর্ডার ফাংশন, সিঙ্ক্রোনাইজেশন ব্লক, স্কোপ ফাংশন (let, apply, also, run)

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন