प्रोग्रामर 3 के लिए Kotlin बूटकैंप: फ़ंक्शन

यह कोडलैब प्रोग्रामर कोर्स के लिए Kotlin बूटकैंप का हिस्सा है. अगर आप कोडलैब के क्रम में काम करते हैं, तो आपको इस कोर्स का ज़्यादा से ज़्यादा फ़ायदा मिलेगा. अपनी जानकारी के आधार पर, आप कुछ सेक्शन को हाइलाइट कर सकते हैं. यह कोर्स उन प्रोग्रामर को ध्यान में रखकर बनाया गया है जो ऑब्जेक्ट पर आधारित भाषा जानते हैं और कोटलिन सीखना चाहते हैं.

परिचय

इस कोडलैब में, आप Kotlin प्रोग्राम बनाते हैं और Kotlin में फ़ंक्शन के बारे में जानते हैं. इसमें पैरामीटर, फ़िल्टर, lambdas, और कॉम्पैक्ट फ़ंक्शन के लिए डिफ़ॉल्ट वैल्यू शामिल हैं.

सिर्फ़ एक नमूने वाला ऐप्लिकेशन बनाने के बजाय, इस कोर्स के पाठ आपकी जानकारी देने के लिए डिज़ाइन किए गए हैं. हालांकि, आप एक-दूसरे से खुद को अलग नहीं कर सकते हैं, ताकि आप उन सेक्शन को हाइलाइट कर सकें जिनसे आप सहमत हैं. इन्हें एक साथ जोड़ने के लिए, कई उदाहरणों में एक्वेरियम की थीम का इस्तेमाल किया गया है. अगर आप पूरी अक्वेरियम की कहानी देखना चाहते हैं, तो प्रोग्रामर के लिए Kotlin बूटकैंप Udacity कोर्स देखें.

आपको क्या पता होना चाहिए

  • बुनियादी तौर पर स्टैटिक फ़ॉर्मैट में टाइप की गई प्रोग्रामिंग लैंग्वेज
  • कक्षाओं, तरीकों, और अपवाद हैंडलिंग के साथ कम से कम एक भाषा में प्रोग्राम कैसे करें
  • IntelliJ IDEA में Kotlin's REPL (Read-Eval-Print Loop) के साथ काम करने का तरीका
  • Kotlin से जुड़ी बुनियादी बातें, जिसमें टाइप, ऑपरेटर, और लूप शामिल हैं

यह कोडलैब ऐसे प्रोग्रामर के लिए है जिनमें ऑब्जेक्ट की जानकारी देने वाली भाषा है और जो Kotlin के बारे में ज़्यादा जानना चाहते हैं.

आप इन चीज़ों के बारे में जानेंगे

  • IntelliJ IDEA में main() फ़ंक्शन और आर्ग्युमेंट वाला प्रोग्राम बनाने का तरीका
  • डिफ़ॉल्ट वैल्यू और छोटे फ़ंक्शन को इस्तेमाल करने का तरीका
  • सूचियों के लिए फ़िल्टर लागू करने का तरीका
  • बुनियादी lambdas और हाई-ऑर्डर फ़ंक्शन बनाने का तरीका

आप क्या कर पाएंगे!

  • कुछ कोड आज़माने के लिए, REPL के साथ काम करें.
  • Kotlin के बुनियादी प्रोग्राम बनाने के लिए, IntelliJ IDEA के साथ काम करें.

इस टास्क में, Kotlin प्रोग्राम बनाएं और main() फ़ंक्शन के बारे में जानें. साथ ही, कमांड लाइन से किसी प्रोग्राम में आर्ग्युमेंट को पास करने का तरीका भी जानें.

आपको किसी पिछले कोडलैब में REPL में डाले गए printHello() फ़ंक्शन को याद आ सकता है:

fun printHello() {
    println ("Hello World")
}

printHello()
⇒ Hello World

आपने fun कीवर्ड का इस्तेमाल करके फ़ंक्शन के बारे में बताया है. इसके बाद फ़ंक्शन का नाम बताया जाता है. अन्य प्रोग्रामिंग भाषाओं की तरह, () ब्रैकेट किसी भी तरह के फ़ंक्शन आर्ग्युमेंट के लिए होते हैं. कर्ली ब्रैकेट {} से फ़ंक्शन के लिए कोड फ़्रेम करते हैं. इस फ़ंक्शन के लिए कोई रिटर्न टाइप नहीं है, क्योंकि इससे कोई रिटर्न नहीं आता.

पहला चरण: Kotlin फ़ाइल बनाएं

  1. IntelliJ IDEA खोलें.
  2. IntelliJ IDEA में बाईं ओर दिया गया प्रोजेक्ट पैनल, आपके प्रोजेक्ट की फ़ाइलों और फ़ोल्डर की सूची दिखाता है. Hello Kotlin में src फ़ोल्डर को ढूंढें और उस पर दायां क्लिक करें. (आपके पास पिछले कोडलैब से नमस्ते Kotlin प्रोजेक्ट पहले से होना चाहिए.)
  3. New > Kotlin फ़ाइल / क्लास चुनें.
  4. Kind को फ़ाइल के तौर पर रखें और फ़ाइल को Hello नाम दें.
  5. ठीक है पर क्लिक करें.

अब src फ़ोल्डर में Hello.kt नाम की एक फ़ाइल मौजूद है.

दूसरा चरण: कोड जोड़ना और प्रोग्राम को चलाना

  1. दूसरी लैंग्वेज के साथ, Kotlin main() फ़ंक्शन प्रोग्राम चलाने के लिए एंट्री पॉइंट के बारे में बताता है. कोई भी कमांड लाइन आर्ग्युमेंट, स्ट्रिंग की श्रेणी के रूप में पास होते हैं.

    नीचे दिए गए कोड को Hello.kt फ़ाइल में टाइप करें या चिपकाएं:
fun main(args: Array<String>) {
    println("Hello, world!")
}

आपके पहले के printHello() फ़ंक्शन की तरह, इस फ़ंक्शन में भी return स्टेटमेंट नहीं है. Kotlin में हर फ़ंक्शन कुछ रिटर्न ज़रूर करता है. चाहे कुछ भी साफ़ तौर पर बताया न गया हो. main() फ़ंक्शन की तरह का फ़ंक्शन, kotlin.Unit टाइप देता है, जो Kotlin's है और कोई वैल्यू नहीं बताता है.

  1. अपना प्रोग्राम चलाने के लिए, main() फ़ंक्शन की बाईं ओर मौजूद हरे रंग के त्रिभुज पर क्लिक करें. मेन्यू से चलाएं 'HelloKt' चुनें.
  2. IntelliJ IDEA प्रोग्राम को कंपाइल करके इसे चलाता है. नतीजे, नीचे दिखाए गए लॉग पैनल में दिखते हैं.

तीसरा चरण: आर्ग्युमेंट को main() में पास करना

कमांड लाइन के बजाय, IntelliJ IDEA से प्रोग्राम को चलाने पर, आपको प्रोग्राम के बारे में किसी भी आर्ग्युमेंट को कुछ अलग ढंग से बताना पड़ेगा.

  1. चलाएं &कॉन्फ़िगरेशन बदलें चुनें. रन/डीबग कॉन्फ़िगरेशन विंडो खुलती है.
  2. प्रोग्राम के आर्ग्युमेंट फ़ील्ड में Kotlin! टाइप करें.
  3. ठीक है पर क्लिक करें.

चौथा चरण: स्ट्रिंग टेंप्लेट का इस्तेमाल करने के लिए कोड बदलना

स्ट्रिंग टेंप्लेट, किसी स्ट्रिंग में वैरिएबल या एक्सप्रेशन डालता है और $ बताता है कि स्ट्रिंग का कोई हिस्सा वैरिएबल या एक्सप्रेशन होगा. कर्ली ब्रैकेट {} को फ़्रेम करता है, अगर कोई हो.

  1. Hello.kt में, "world" के बजाय args[0] में प्रोग्राम को पास किए गए पहले आर्ग्युमेंट का इस्तेमाल करने के लिए, अभिवादन के मैसेज को बदलें.
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. प्रोग्राम को चलाएं और आउटपुट में आपके दिए हुए तर्क शामिल हैं.
⇒ Hello, Kotlin!

इस टास्क में, आप जानते हैं कि Kotlin में मौजूद करीब-करीब हर चीज़ की वैल्यू क्यों है और यह #39 उपयोगी क्यों है.

कुछ अन्य भाषाओं के स्टेटमेंट होते हैं, जो कोड की लाइनें होती हैं और इनकी कोई वैल्यू नहीं होती. Kotlin में, करीब-करीब हर चीज़ का कोई एक्सप्रेशन होता है और उसका कोई मान होता है—भले ही वह मान kotlin.Unit हो.

  1. Hello.kt में, isUnit नाम के वैरिएबल को println() असाइन करने और उसे प्रिंट करने के लिए, main() में कोड लिखें. (println() वैल्यू को रिटर्न नहीं करता है, इसलिए यह kotlin.Unit को दिखाता है.)
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. प्रोग्राम चलाएं. पहली println() स्ट्रिंग "This is an expression" को प्रिंट करती है. दूसरा println() पहले println() स्टेटमेंट की वैल्यू को प्रिंट करता है, जो कि kotlin.Unit होता है.
⇒ This is an expression
kotlin.Unit
  1. temperature नाम के val का एलान करें और उसे 10 पर शुरू करें.
  2. isHot के तौर पर val नाम का एक और एलान करें. साथ ही, isHot को if/else का रिटर्न मान असाइन करें, जैसा कि नीचे दिए गए कोड में दिखाया गया है. यह एक एक्सप्रेशन है, इसलिए आप if एक्सप्रेशन की वैल्यू का तुरंत इस्तेमाल कर सकते हैं.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. स्ट्रिंग टेंप्लेट में, एक्सप्रेशन की वैल्यू का इस्तेमाल करें. यह पता करने के लिए कि मछली सुरक्षित है या बहुत ज़्यादा गर्म है, कुछ कोड जोड़ें. इसके बाद, अपना प्रोग्राम चलाएं.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

इस टास्क में, आपको Kotlin में फ़ंक्शन के बारे में ज़्यादा जानकारी मिलती है. साथ ही, यह कंडीशनल एक्सप्रेशन के बारे में भी ज़्यादा जानकारी देता है when.

पहला चरण: कुछ फ़ंक्शन बनाना

इस कदम में, आपने जो कुछ सीखा है उसे अलग-अलग टाइप के साथ रखें और उसे एक साथ बनाएं. Hello.kt के कॉन्टेंट को नए कोड से बदला जा सकता है.

  1. feedTheFish() नाम का एक फ़ंक्शन लिखें, जो randomDay() को हफ़्ते के किसी भी दिन कॉल करे. स्ट्रिंग के टेंप्लेट का इस्तेमाल करके प्रिंट करें कि food उस दिन मछली को खाना चाहेंगे या नहीं. फ़िलहाल, मछली एक ही खाना हर दिन खाती है.
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. किसी श्रेणी से किसी भी दिन को चुनने और उसे लौटाने के लिए, randomDay() फ़ंक्शन लिखें.

nextInt() फ़ंक्शन एक पूर्णांक सीमा लेता है, जो week श्रेणी से मेल खाने के लिए संख्या को Random() से 0 तक सीमित करता है.

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Random() और nextInt() फ़ंक्शन java.util.* में बताए गए हैं. फ़ाइल के ऊपर, ज़रूरी इंपोर्ट जोड़ें:
import java.util.*    // required import
  1. प्रोग्राम चलाएं और आउटपुट देखें.
⇒ Today is Tuesday and the fish eat pellets

दूसरा चरण: एक्सप्रेशन के दौरान कब इस्तेमाल करें

कोड को बदलकर, when एक्सप्रेशन का इस्तेमाल करके अलग-अलग दिनों के लिए अलग-अलग दिन का कोड चुनें. when स्टेटमेंट दूसरी प्रोग्रामिंग भाषाओं में switch से मिलता-जुलता है. हालांकि, हर ब्रांच के आखिर में when अपने-आप अलग हो जाता है. अगर आप enum की जांच कर रहे हैं, तो यह भी पक्का करता है कि आपके कोड में सभी ब्रांच शामिल हों.

  1. Hello.kt में, fishFood() नाम का एक फ़ंक्शन जोड़ें. यह एक दिन को String के तौर पर लेता है और उस दिन के लिए, मछली और #39; का खाना String के तौर पर दिखाता है. when() का इस्तेमाल करें, ताकि हर दिन मछली को एक खास खाना मिले. अलग-अलग आउटपुट देखने के लिए, अपने प्रोग्राम को कई बार चलाएं.
fun fishFood (day : String) : String {
    var food = ""
    when (day) {
        "Monday" -> food = "flakes"
        "Tuesday" -> food = "pellets"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Saturday" -> food = "lettuce"
        "Sunday" -> food = "plankton"
    }
    return food
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)

    println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
  1. else का इस्तेमाल करके when एक्सप्रेशन में एक डिफ़ॉल्ट ब्रांच जोड़ें. जांच के लिए, यह पक्का करने के लिए कि आपके प्रोग्राम में कभी-कभी डिफ़ॉल्ट वैल्यू ली जाती है, Tuesday और Saturday ब्रांच हटाएं.

    डिफ़ॉल्ट ब्रांच होने पर, यह पक्का किया जाता है कि वैल्यू देने से पहले food को वैल्यू दी जा रही है. इसलिए, अब इसे शुरू करना ज़रूरी नहीं है. अब कोड सिर्फ़ food को एक स्ट्रिंग असाइन करता है. इसलिए, आप var के बजाय, val के साथ food तय कर सकते हैं.
fun fishFood (day : String) : String {
    val food : String
    when (day) {
        "Monday" -> food = "flakes"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Sunday" -> food = "plankton"
        else -> food = "nothing"
    }
    return food
}
  1. हर एक्सप्रेशन की एक वैल्यू होती है, इसलिए आप इस कोड को और छोटा बना सकते हैं. when एक्सप्रेशन की वैल्यू को सीधे तौर पर रिटर्न करें और food वैरिएबल को हटाएं. when एक्सप्रेशन की वैल्यू, ब्रांच के आखिरी एक्सप्रेशन की वैल्यू होती है जो शर्त को पूरा करती है.
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

आपके प्रोग्राम का फ़ाइनल वर्शन, नीचे दिए गए कोड जैसा दिखता है.

import java.util.*    // required import

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}

fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}

इस टास्क में, आपको फ़ंक्शन और मेथड के डिफ़ॉल्ट मानों के बारे में पता चलता है. आप कॉम्पैक्ट फ़ंक्शन के बारे में भी जानते हैं, जो आपके कोड को छोटा और पढ़ने लायक बना सकते हैं. साथ ही, इससे टेस्ट के लिए कोड पाथ की संख्या कम हो सकती है. कॉम्पैक्ट फ़ंक्शन को एक एक्सप्रेशन वाले फ़ंक्शन भी कहा जाता है.

पहला कदम: पैरामीटर के लिए एक डिफ़ॉल्ट वैल्यू बनाना

Kotlin में, पैरामीटर के नाम के हिसाब से आर्ग्युमेंट पास किए जा सकते हैं. आप पैरामीटर के लिए डिफ़ॉल्ट मान भी तय कर सकते हैं: अगर कॉल करने वाले (कॉलर) ने कोई आर्ग्युमेंट नहीं दिया है, तो डिफ़ॉल्ट वैल्यू का इस्तेमाल किया जाता है. बाद में, जब आप मैथड (सदस्य फ़ंक्शन) लिखते हैं, तो इसका मतलब है कि आप एक ही तरीके के बहुत ज़्यादा ओवरलोड वर्शन लिखने से बच सकते हैं.

  1. Hello.kt में, speed नाम के String पैरामीटर के साथ swim() फ़ंक्शन लिखें. इससे मछली की #39; गति को प्रिंट किया जाता है. speed पैरामीटर की डिफ़ॉल्ट वैल्यू "fast" है.
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. main() फ़ंक्शन से, swim() फ़ंक्शन को तीन तरह से कॉल करें. पहले डिफ़ॉल्ट का इस्तेमाल करके फ़ंक्शन को कॉल करें. इसके बाद, फ़ंक्शन को कॉल करें और बिना नाम के speed पैरामीटर को पास करें. इसके बाद, speed पैरामीटर को नाम देकर, फ़ंक्शन को कॉल करें.
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

दूसरा चरण: ज़रूरी पैरामीटर जोड़ना

अगर किसी पैरामीटर के लिए कोई भी डिफ़ॉल्ट तय नहीं है, तो उससे जुड़े आर्ग्युमेंट हमेशा पास किए जाने चाहिए.

  1. Hello.kt में, तीन फ़ंक्शन लेने वाला एक shouldChangeWater() फ़ंक्शन लिखें: day, temperature, और एक dirty लेवल. अगर पानी बदला जाता है, तो फ़ंक्शन true लौटाता है. ऐसा तब होता है, जब पानी रविवार को ज़्यादा होता है, तापमान ज़्यादा रहता है या पानी बहुत ज़्यादा होता है. हफ़्ते का दिन ज़रूरी है, लेकिन डिफ़ॉल्ट तापमान 22 है और डिफ़ॉल्ट गंदा लेवल 20 है.

    आर्ग्युमेंट के बिना when एक्सप्रेशन का इस्तेमाल करें, जो Kotlin में if/else if चेक सीरीज़ के तौर पर काम करता है.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        temperature > 30 -> true
        dirty > 30 -> true
        day == "Sunday" ->  true
        else -> false
    }
}
  1. feedTheFish() से shouldChangeWater() को कॉल करें और दिन की जानकारी दें. day पैरामीटर में डिफ़ॉल्ट नहीं है, इसलिए आपको कोई तर्क बताना होगा. shouldChangeWater() के दूसरे दो पैरामीटर की डिफ़ॉल्ट वैल्यू हैं, इसलिए आपको उनके लिए आर्ग्युमेंट पास नहीं करने होंगे.
fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
    println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules
Change water: false

तीसरा चरण: कॉम्पैक्ट फ़ंक्शन करना

पिछले चरण में आपने when का जो एक्सप्रेशन लिखा है वह बहुत कम कोड में बहुत सारे लॉजिक पैक करता है. अगर आप इसे थोड़ा सा अनपैक करना चाहते हैं या अगर जांच करने की शर्तें ज़्यादा मुश्किल हैं, तो आप कुछ मशहूर स्थानीय वैरिएबल का इस्तेमाल कर सकते हैं. हालांकि, Kotlin फ़ंक्शन को छोटे फ़ंक्शन में इस्तेमाल किया जा सकता है.

कॉम्पैक्ट फ़ंक्शन या एक एक्सप्रेशन वाले फ़ंक्शन, Kotlin में एक सामान्य पैटर्न हैं. जब फ़ंक्शन किसी एक एक्सप्रेशन के नतीजे देता है, तो आप = सिंबल के बाद, फ़ंक्शन का मुख्य हिस्सा बता सकते हैं. कर्ली ब्रैकेट {} को हटा सकते हैं और return को हटा सकते हैं.

  1. Hello.kt में, शर्तों की जांच करने के लिए कॉम्पैक्ट फ़ंक्शन जोड़ें.
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. नए फ़ंक्शन को कॉल करने के लिए, shouldChangeWater() बदलें.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        isTooHot(temperature) -> true
        isDirty(dirty) -> true
        isSunday(day) -> true
        else  -> false
    }
}
  1. प्रोग्राम चलाएं. shouldChangeWater() के साथ println() का आउटपुट वही होना चाहिए जो आपने संक्षिप्त फ़ंक्शन का इस्तेमाल करने से पहले किया था.

डिफ़ॉल्ट मान

पैरामीटर का डिफ़ॉल्ट मान'होना चाहिए. यह एक और फ़ंक्शन हो सकता है, जैसा कि नीचे दिए गए आंशिक सैंपल में दिखाया गया है:

fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
    ...

इस टास्क में, आपको Kotlin में फ़िल्टर के बारे में कुछ जानकारी मिलती है. कुछ स्थितियों के आधार पर बनी सूची का कुछ हिस्सा देखने के लिए, फ़िल्टर इस्तेमाल करने का एक आसान तरीका है.

पहला चरण: फ़िल्टर बनाना

  1. Hello.kt में, listOf() के साथ टॉप लेवल पर एक्वेरियम की सजावट की सूची तय करें. Hello.kt का कॉन्टेंट बदला जा सकता है.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. सिर्फ़ डेकोरेशन से जुड़ी लाइन को प्रिंट करने के लिए, नया main() फ़ंक्शन बनाएं. यह अक्षर 'p' से शुरू होता है. फ़िल्टर स्थिति का कोड कर्ली ब्रैकेट {} में है और it हर आइटम को फ़िल्टर लूप से जोड़ता है. अगर एक्सप्रेशन true दिखाता है, तो आइटम शामिल है.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. प्रोग्राम चलाएं और चलाएं विंडो में यह आउटपुट दिखेगा:
⇒ [pagoda, plastic plant]

चरण 2: ईगर और लेज़ी फ़िल्टर की तुलना करें

अगर आप दूसरी भाषाओं के फ़िल्टर से परिचित हैं, तो आप सोच सकते हैं कि Kotlin में फ़िल्टर ईगर हैं या लेज़ी. क्या नतीजे की सूची तुरंत बना दी जाती है या सूची को ऐक्सेस किया जाता है? Kotlin में, आपकी ज़रूरत के हिसाब से ऐसा किया जाता है. डिफ़ॉल्ट रूप से, filter ईगर होते हैं और हर बार जब आप फ़िल्टर इस्तेमाल करते हैं, तो एक लिस्ट बनती है.

लेज़ी फ़िल्टर बनाने के लिए, आप Sequence का इस्तेमाल कर सकते हैं. यह ऐसा कलेक्शन होता है जो एक समय पर सिर्फ़ एक ही आइटम को देखता है. इसकी शुरुआत शुरू से होती है और आखिर में जाकर खत्म होती है. आसानी से, यही वह एपीआई है जो लेज़ी फ़िल्टर के लिए ज़रूरी है.

  1. Hello.kt में, फ़िल्टर की गई सूची को eager नाम के वैरिएबल को असाइन करने के लिए, अपना कोड बदलें. इसके बाद, उसे प्रिंट करें.
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: " + eager)
  1. उस कोड के नीचे, asSequence() वाले Sequence का इस्तेमाल करके, फ़िल्टर को इवैलुएट करें. filtered वैरिएबल को क्रम असाइन करें और उसे प्रिंट करें.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

जब आप फ़िल्टर के नतीजों को Sequence के तौर पर दिखाते हैं, तो filtered वैरिएबल नई सूची को होल्ड पर रखता है—और यह #39 होता है. इन एलिमेंट पर लागू करने के लिए, सूची एलिमेंट का Sequence और फ़िल्टर की जानकारी होती है. जब भी आप Sequence के एलिमेंट ऐक्सेस करते हैं, तो फ़िल्टर लागू हो जाता है और नतीजा आपको वापस मिल जाता है.

  1. क्रम को toList() के साथ List में बदलकर उसका इवैलुएशन करें. नतीजा प्रिंट करें.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. अपना प्रोग्राम चलाएं और आउटपुट पर नज़र रखें.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Sequence और लेज़ी इवैलुएशन के साथ, यह देखने के लिए कि क्या' आ रहा है, map() फ़ंक्शन का इस्तेमाल करें. map() फ़ंक्शन, क्रम में हर एलिमेंट पर आसान बदलाव करता है.

  1. ऊपर दी गई decorations सूची का इस्तेमाल करके, map() से बदलाव करें. इससे कोई बदलाव नहीं होगा. साथ ही, पास किए गए एलिमेंट को दिखाएगा. हर बार एलिमेंट ऐक्सेस करने पर दिखाने के लिए एक println() जोड़ें और lazyMap नाम के वैरिएबल को क्रम असाइन करें.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. lazyMap का प्रिंट लें, first() का इस्तेमाल करके lazyMap का पहला एलिमेंट प्रिंट करें, और lazyMap का प्रिंट List में बदलें.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. अपना प्रोग्राम चलाएं और आउटपुट पर नज़र रखें. lazyMap प्रिंट करने से, सिर्फ़ Sequence का रेफ़रंस प्रिंट होता है—अंदरूनी println() कहा नहीं जाता और #39;नहीं. पहला एलिमेंट प्रिंट करने से सिर्फ़ पहला एलिमेंट ऐक्सेस होता है. Sequence को List में बदलने से सभी एलिमेंट ऐक्सेस हो जाते हैं.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. map को लागू करने से पहले, मूल फ़िल्टर का इस्तेमाल करके एक नया Sequence बनाएं. उस नतीजे को प्रिंट करें.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. अपना प्रोग्राम चलाएं और अतिरिक्त आउटपुट की निगरानी करें. पहला एलिमेंट मिलने की तरह, अंदरूनी println() सिर्फ़ उन एलिमेंट के लिए कॉल किया जाता है जिन्हें ऐक्सेस किया जाता है.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

इस टास्क में, आपको Kotlin में lambdas और हाई-ऑर्डर फ़ंक्शन के बारे में जानकारी मिलती है.

Lambdas

पारंपरिक नाम वाले फ़ंक्शन के साथ ही, Kotlin में lambdas पर काम किया जा सकता है. lambda एक एक्सप्रेशन है, जो फ़ंक्शन बनाता है. नाम वाले फ़ंक्शन का एलान करने के बजाय, आपने बिना नाम वाले फ़ंक्शन का एलान किया है. यह बात lambda एक्सप्रेशन को काम का बनाती है कि इसे अब डेटा के तौर पर भेजा जा सकता है. अन्य लैंग्वेज में, lambdas को पहचान छिपाकर किए जाने वाले फ़ंक्शन, फ़ंक्शन लिटरल या मिलते-जुलते नाम से जाना जाता है.

हाई-ऑर्डर फ़ंक्शन

Lambda को किसी दूसरे फ़ंक्शन में पास करके, आप हाई-ऑर्डर फ़ंक्शन बना सकते हैं. पिछले टास्क में, आपने हाई-ऑर्डर फ़ंक्शन बनाया था. इसका नाम filter है. आपने स्थिति के तौर पर filter को यह Lambda का एक्सप्रेशन पास किया है:
{it[0] == 'p'}

इसी तरह, map एक हाई-ऑर्डर फ़ंक्शन है और आपने जो lambda को पास किया था वह बदलाव करने के लिए बदलाव था.

पहला चरण: Lambdas के बारे में जानें

  1. नाम वाले फ़ंक्शन की तरह, lambdas के भी पैरामीटर हो सकते हैं. Lambdas के लिए, पैरामीटर (और उनके टाइप, अगर ज़रूरी हों) किसी फ़ंक्शन ऐरो -> की बाईं ओर होते हैं. एक्ज़ीक्यूट करने के लिए कोड, फ़ंक्शन ऐरो की दाईं ओर होते हैं. जब Lambda को किसी वैरिएबल को असाइन किया जाता है, तो आप उसे एक फ़ंक्शन की तरह इस्तेमाल कर सकते हैं.

    REPL (टूल > Kotlin > Kotlin REPL) का इस्तेमाल करके, यह कोड आज़माएं:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

इस उदाहरण में, Lambda, dirty नाम वाला Int लेता है और dirty / 2 दिखाता है. (क्योंकि फ़िल्टर करने से धूल नहीं हटती.)

  1. फ़ंक्शन टाइप के लिए Kotlin सिंटैक्स, काफ़ी हद तक lambdas के लिए Kotlin सिंटैक्स से मिलता-जुलता है. इस सिंटैक्स का इस्तेमाल करके, किसी फ़ंक्शन वाले वैरिएबल के बारे में साफ़ तौर पर बताएं:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

कोड यह कहता है:

  • waterFilter नाम का वैरिएबल बनाएं.
  • waterFilter कोई भी ऐसा फ़ंक्शन हो सकता है जो Int को लेता है और Int दिखाता है.
  • Lambda को waterFilter के लिए असाइन करें.
  • Lambda आर्ग्युमेंट के वैल्यू को dirty से भाग करके, दो से भाग देता है.

ध्यान दें कि अब आपको lambda आर्ग्युमेंट के टाइप को बताने की ज़रूरत नहीं है. टाइप का हिसाब टाइप अनुमान से लगाया जाता है.

दूसरा चरण: हाई-ऑर्डर फ़ंक्शन बनाना

अब तक, Lambdas के उदाहरण ज़्यादातर फ़ंक्शन की तरह दिखते हैं. Lambdas की असली ताकत है उसे इस्तेमाल करके, ऐसा हाई-ऑर्डर फ़ंक्शन बनाना जहां किसी एक फ़ंक्शन का आर्ग्युमेंट, दूसरा फ़ंक्शन हो.

  1. हाई-ऑर्डर फ़ंक्शन लिखें. यहां एक बुनियादी उदाहरण दिया गया है. यह एक फ़ंक्शन है, जो दो आर्ग्युमेंट लेता है. पहला तर्क एक पूर्णांक है. दूसरा आर्ग्युमेंट एक फ़ंक्शन है जो इंटेजर लेता है और इंटेजर रिटर्न करता है. इसे REPL में आज़माएं.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

कोड का मुख्य हिस्सा, उस फ़ंक्शन को कॉल करता है जो दूसरे आर्ग्युमेंट के तौर पर पास हुआ था. साथ ही, पहले आर्ग्युमेंट को पास करता है.

  1. इस फ़ंक्शन को कॉल करने के लिए, इसे पूर्णांक और फ़ंक्शन पास करें.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

आपने जो फ़ंक्शन पास किया है वह Lambda का नहीं है, यह नाम वाले फ़ंक्शन की तरह ही हो सकता है. किसी रेगुलर फ़ंक्शन के तौर पर आर्ग्युमेंट के बारे में बताने के लिए, :: ऑपरेटर का इस्तेमाल करें. इस तरह, Kotlin को पता चलता है कि आप फ़ंक्शन रेफ़रंस को आर्ग्युमेंट के तौर पर पास कर रहे हैं, फ़ंक्शन को कॉल करने की कोशिश नहीं कर रहे हैं.

  1. updateDirty() को कोई रेगुलर नाम वाला फ़ंक्शन भेजकर देखें.
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • IntelliJ IDEA में Kotlin सोर्स फ़ाइल बनाने के लिए, Kotlin प्रोजेक्ट से शुरुआत करें.
  • IntelliJ IDEA में किसी प्रोग्राम को कंपाइल करने और चलाने के लिए, main() फ़ंक्शन के बगल में मौजूद हरे त्रिभुज पर क्लिक करें. आउटपुट नीचे लॉग विंडो में दिखता है.
  • IntelliJ IDEA में, चलाएं और कॉन्फ़िगरेशन में बदलाव करें; कॉन्फ़िगरेशन में main() फ़ंक्शन को पास करने के लिए, कमांड लाइन आर्ग्युमेंट डालें.
  • Kotlin में करीब-करीब हर चीज़ की वैल्यू होती है. आप इस तथ्य का इस्तेमाल if या when की वैल्यू को एक्सप्रेशन या रिटर्न वैल्यू के तौर पर करके, अपने कोड को और छोटा बना सकते हैं.
  • डिफ़ॉल्ट तर्क, किसी फ़ंक्शन या तरीके के एक से ज़्यादा वर्शन की ज़रूरत को हटा देते हैं. उदाहरण के लिए:
    fun swim(speed: String = "fast") { ... }
  • कॉम्पैक्ट फ़ंक्शन या एक एक्सप्रेशन वाले फ़ंक्शन, आपके कोड को पढ़ने में आसान बना सकते हैं. उदाहरण के लिए:
    fun isTooHot(temperature: Int) = temperature > 30
  • आपने lambda एक्सप्रेशन का इस्तेमाल करने वाले फ़िल्टर के बारे में कुछ बुनियादी बातें सीखी हैं. उदाहरण के लिए:
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • lambda एक्सप्रेशन एक एक्सप्रेशन है, जो बिना नाम वाला फ़ंक्शन बनाता है. Lambda के एक्सप्रेशन कर्ली ब्रैकेट {} के बीच तय किए जाते हैं.
  • हाई-ऑर्डर फ़ंक्शन में, आप lambda एक्सप्रेशन जैसे किसी फ़ंक्शन को डेटा के तौर पर किसी दूसरे फ़ंक्शन में पास करते हैं. उदाहरण के लिए:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

इस लेसन में बहुत कुछ है. खास तौर पर, अगर आप #lambdas के लिए नए हैं. बाद के पाठ में, lambdas और हाई-ऑर्डर फ़ंक्शन को फिर से देखा जा सकता है.

Kotlin दस्तावेज़

अगर आपको इस कोर्स के किसी विषय के बारे में ज़्यादा जानकारी चाहिए या आपको कोई समस्या आती है, तो आप https://kotlinlang.org से शुरुआत कर सकते हैं.

Kotlin ट्यूटोरियल

https://try.kotlinlang.org वेबसाइट पर, Kotlin कोन्स नाम के रिच ट्यूटोरियल शामिल हैं, जो वेब पर आधारित अनुवादक है. साथ ही, इसमें रेफ़रंस दस्तावेज़ का पूरा सेट भी शामिल है, जिसमें उदाहरण भी दिए गए हैं.

Udcity कोर्स

इस विषय पर Udacity कोर्स देखने के लिए, प्रोग्रामर के लिए Kotlin बूटकैंप देखें.

IntelliJ IDEA

JetBrains वेबसाइट पर, InliJ IDEA के दस्तावेज़ देखे जा सकते हैं.

इस सेक्शन में उन छात्र-छात्राओं के लिए गृहकार्य की असाइनमेंट की सूची दी गई है जो इस कोडलैब के ज़रिए एक शिक्षक की देखरेख में कोर्स में काम कर रहे हैं. यह क्रिएटर का काम #33 पर निर्भर करता है:

  • अगर ज़रूरी हो, तो होमवर्क असाइन करें.
  • छात्र-छात्राओं को होमवर्क के असाइनमेंट सबमिट करने के तरीके के बारे में बताएं.
  • होमवर्क असाइनमेंट को ग्रेड दें.

शिक्षक इन सुझावों का इस्तेमाल जितनी चाहें उतनी कम या ज़्यादा कर सकते हैं. साथ ही, उन्हें अपने हिसाब से कोई भी होमवर्क असाइन करना चाहिए.

अगर आप इस कोडलैब के ज़रिए खुद काम कर रहे हैं, तो बेझिझक इन होमवर्क असाइनमेंट का इस्तेमाल करें.

इन सवालों के जवाब दें

पहला सवाल

अगर contains(element: String) स्ट्रिंग में शामिल स्ट्रिंग contains(element: String) में शामिल है, तो यह contains(element: String) फ़ंक्शन true दिखाता है. नीचे दिए गए कोड का आउटपुट क्या होगा?

val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

println(decorations.filter {it.contains('p')})

[pagoda, plastic, plant]

[pagoda, plastic plant]

[pagoda, plastic plant, flowerpot]

[rock, alligator]

दूसरा सवाल

नीचे दी गई फ़ंक्शन की परिभाषा में, इनमें से किस पैरामीटर की ज़रूरत है?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

तीसरा सवाल

आप किसी सामान्य नाम वाले फ़ंक्शन (न कि कॉल करने का नतीजा) को किसी दूसरे फ़ंक्शन को पास कर सकते हैं. आप increaseDirty( start: Int ) = start + 1 को updateDirty(dirty: Int, operation: (Int) -> Int) के पास कैसे भेजेंगे?

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

updateDirty(15, ("increaseDirty()"))

updateDirty(15, ::increaseDirty)

अगले लेसन पर जाएं: 4. क्लास और ऑब्जेक्ट

कोर्स के बारे में खास जानकारी पाने के लिए, दूसरे कोडलैब के लिंक के साथ-साथ, &kot;Kotlin बूटकैंपर के लिए प्रोग्राम: कोर्स में आपका स्वागत है.