توابع مرتبه بالا در کاتلین

توابع مرتبه بالا

تابع مرتبه بالا

در کاتلین همه چیز object و دارای مقدار است حتی یک تابع.

توابع در کاتلین first-class هستند یعنی میتونیم به یک متغیر اختصاصشون بدیم، به عنوان پارامتر به یک تابع دیگه پاس بدیم، به عنوان مقدار از یک تابع دیگه برشون گردونیم و در ساختار داده مرتبشون کنیم.

تابع مرتبه بالا (Higher-order function) به تابعی گفته میشه که حداقل یک تابع به عنوان پارامتر بگیره یا یک تابع به عنوان مقدار برگردونه.

برای تعریف توابع مرتبه بالا در کاتلین معمولا از توابع تحت لفظی به عنوان پارامتر یا مقدار بازگشتی استفاده میکنیم.

میتونیم از توابع تحت لفظی در پارامتر به عنوان callback استفاده کنیم.

تابع setOnClickListener در اپلیکیشن نویسی معروفه و در اندروید زیاد استفاده میشه این تابع تقریبا مثل زیر تعریف شده و onclick یک callback برای setOnClickListener است.

setOnClickListener(onClick: (view: View) -> Unit){ var view: View = ... ... onClick(view) ... }

صدا زدن تابع:

setOnClickListener({ v -> //Callback ... })

در بالا ‎{ v -> ...} مقدار لامبداییه که به پارامتر اختصاص دادیم.

توجه:

هنگامی که عبارت لامبدا به عنوان اخرین پارامتر تابع تعریف شده باشه، در کاتلین موقع صدا زدن تابع میتونیم لامبدا رو بیرون از پرانتز به پارامتر اختصاص بدیم.

مثال:

در زیر تابع myForeach وظیفه ی خوندن اعضای یک ارایه رو به عهده داره myForeach یک تابع اکستنشن نیز است. مشابه تابع myForeach یک تابع به اسم foreach در api رسمی کاتلین وجود داره.

fun <E> Array<E>.myForeach(accessor: (element: E) -> Unit){ for(e in this) accessor(e) }

صدا زدن تابع:

fun main(){ val arr = arrayOf<Int>(9, 10, 8, 2, 1) arr.myForeach{ element -> print("$element "); } }

مثال:

در زیر یک تابع مرتبه بالا داریم که کارکتر های تصادفی درست میکنه و با استفاده از accessible با هربار تولید کارکتر میتونیم به اون کارکتر به صورت Callback توسط لامبدا دسترسی داشته باشیم و در پایان کار تابع همه ی کاراکتر ها رو به صورت String بر میگردونه.

fun main(){ val NUMBER_OF_CHARS_PER_LINE = 12 println("Printing random chars") //صدا زدن تابع val randomChars: String = generateRandomChars(200, 'A', 'Z') { //اختصاص دادن لامبدا به اخرین پارامتر ch , index -> if((index + 1) % NUMBER_OF_CHARS_PER_LINE == 0) println(ch) else print(ch) } println("Returned chars from generateRandomChars: ") println(randomChars) } //تعریف تابع fun generateRandomChars(length: Int, startRange: Char, endRange: Char, accessible: (generated: Char, index: Int) -> Unit): String{ val start = startRange.code val end = endRange.code var result = "" for(index in 0 until length){ val ch = (start + Math.random() * (end - start + 1)).toInt().toChar() //صدا زدن لامبدا accessible(ch, index) result += ch } return result }

تعریف تابع تحت لفظی با receiver به عنوان پارامتر

توجه:

برای درک بهتر این قسمت خوبه که با شی گرایی و ساخت نمونه از کلاس اشنایی داشته باشید

میتونیم توابع تحت لفظی با رسیور رو به عنوان پارامتر برای تابع مرتبه بالا تعریف کنیم. مهم ترین کاربردشون در type-safe builder ها است.

مثال:

مثال زیر در وبسایت رسمی کاتلین قرار داره و نشون میده توابعی که در کاتلین برای ایجاد تگ های html وجود دارن چطور تعریف شدن.

این مثال فقط برای تفهیم موضوعه و قابل اجرا نیست.

class HTML { fun body() { ... } } fun html(init: HTML.() -> Unit): HTML { val h = HTML() // ساخت نمونه از رسیور h.init() // صدا زدن عبارت لامبدا return h } html { // مقداردهی عبارت لامبدا با رسیور به عنوان پارامتر تابع ... body() // صدا زدن اعضای رسیور ... }

خلاصه

- در کاتلین توابع first-class هستند

- تابع مرتبه بالا به تابعی گفته میشه که حداقل یک تابع به عنوان پارامتر دریافت کنه یا یک تابع به عنوان مقدار برگردونه.

- معمولا از توابع تحت اللفظی به عنوان پارامتر تابع مرتبه بالا استفاده میشه.

- میتونیم از پارامتر هایی که با توابع تحت اللفطی تعریف میکنیم به عنوان Callback استفاده کنیم.

- تابع setOnClickListener در api اپلیکیشن ها از جمله اندروید، توابع مرتبه بالا هستند.

- میتونیم تابع با رسیور رو به عنوان پارامتر تابع مرتبه بالا تعریف کنیم.

- با تعریف تابع با رسیور به عنوان پارامتر تابع مرتبه بالا میتونیم type-safe builder تعریف کنیم.

arrow_drop_up
کپی شد!