در این تکلیف، لامبداها و تابعهای مرتبه بالاتر در کاتلین به شما معرفی میشود.
لامبداها
علاوه بر تابعهای معمول، کاتلین از لامبداها هم پشتیبانی میکند. یک لامبدا یک عبارت است که یک تابع میسازد. اما بهجای اعلام کردن یک تابع با نام، یک تابع بدون نام اعلام میکنید. فایدهاش این است که حالا عبارت لامبدا میتواند به عنوان داده واگذار شود. در سایر زبانها لامبداها به توابع ناشناس ، توابع literal یا نام هایی از این قبیل شناخته میشوند.
توابع مرتبه بالاتر
شما میتوانید توابع مرتبه بالاتر را با واگذار کردن یک لامبدا به یک تابع دیگر بسازید. در تکلیف قبلی، شما یک تابع مرتبه بالاتر به نام filter ساختید. شما عبارت لامبدای زیر را به عنوان شرطی برای آزمودن به filter واگذار کردید: {it[0] == 'p'}
به همین شکل، map یک تابع مرتبه بالا است، و لامبدایی که به آن واگذار کردید یک تبدیل برای اعمال شدن بود.
گام 1: درباره لامبداها بیاموزید
با استفاده از REPL این کد را امتحان کنید:
var dirtyLevel = 20 val waterFilter = { dirty : Int -> dirty / 2} println(waterFilter(dirtyLevel)) ⇒ 10
در این مثال، لامبدا یک Int به نام dirty میگیرد، و 2 / dirty را برمیگرداند. (چون فیلتر کردن کثیفی را از بین میبرد.)
2. نحو کاتلین برای نوعهای تابع به طرز نزدیکی به نحو لامبداها ارتباط دارد. از این نحو برای اعلام تمیز یک متغیر که یک تابع نگهمیدارد استفاده کنید:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
این چیزی است که کد میگوید:
توجه کنید که لازم نیست دیگر نوع آرگومان لامبدا را مشخص کنید. نوع بر اساس استنباط نوع محاسبه میشود.
گام 2: یک تابع مرتبه بالاتر بسازید
تا به اینجا، مثالهای لامبدا مثل تابع به نظر میرسید. قدرت واقعی لامبداها در ساختن توابع مرتبه بالاتر است، جایی که آرگومان یک تابع، تابع دیگری است.
1. یک تابع مرتبه بالاتر بنویسید. این یک مثال ساده است، یک تابع که دو آرگومان میگیرد. آرگومان اول یک عددصحیح است. آرگومان دوم یک تابع است که یک عدد صحیح میگیرد و یک عدد صحیح برمیگرداند. در REPL امتحان کنید:
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int { return operation(dirty) }
بدنه کد تابع واگذار شده به عنوان آرگومان دوم را صدا میزند، و آرگومان دوم را به آن واگذار میکند.
2. این تابع را صدا بزنید، یک عدد صحیح و یک تابع به آن واگذار کنید.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 } println(updateDirty(30, waterFilter)) ⇒ 15
تابعی که واگذار میکنید نیازی نیست لامبدا باشد، میتواند یک تابع با نامِ معمول باشد. برای مشخص کردن آرگومان به عنوان تابع معمولی، از عملگر :: استفاده کنید. اینگونه کاتلین متوجه میشود شما منبع تابع را به عنوان آرگومان واگذار میکنید و نمیخواهید تابع را صدا بزنید.
3. واگذار کردن یک تابع با نام معمول به ()updateDirty را امتحان کنید.
fun increaseDirty( start: Int ) = start + 1 println(updateDirty(15, ::increaseDirty)) ⇒ 16
کاتلین ترجیح میدهد پارامتری که تابع میگیرد آخرین پارامتر باشد. وقتی با توابع مرتبه بالاتر کار میکند، کاتلین نحو خاصی دارد، که به نحو صدا زدن آخرین پارامتر شناخته میشود، که به شما امکان مختصر ساختن کد را میدهد. در این مورد، شما میتواند یک لامبدا به عنوان پارامتر تابع واگذار کنید، اما شما نیازی به قرار دادن لامبدا داخل پرانتز ندارید.
var dirtyLevel = 19; dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23} println(dirtyLevel) ⇒ 42