Dùng các loại hàm và biểu thức lambda trong Kotlin

1. Giới thiệu

Lớp học lập trình này hướng dẫn bạn về các loại hàm, cách sử dụng các loại hàm và cú pháp dành riêng cho biểu thức lambda.

Trong Kotlin, hàm được coi là cấu trúc lớp thứ nhất (first-class constructs). Điều này có nghĩa là hàm có thể được coi là một loại dữ liệu. Bạn có thể lưu trữ hàm trong biến, truyền hàm đó vào hàm khác dưới dạng đối số và trả về hàm đó từ hàm khác.

Giống như các loại dữ liệu khác mà bạn có thể biểu thị bằng giá trị cố định – chẳng hạn như loại Int có giá trị 10 và loại String có giá trị "Hello" – bạn cũng có thể khai báo giá trị cố định hàm (được gọi là biểu thức lambda hoặc gọi tắt là lambda). Việc sử dụng biểu thức lambda được áp dụng rộng rãi trong phát triển nội dung Android và thường xuyên trong lập trình Kotlin.

Điều kiện tiên quyết

  • Quen thuộc với lập trình Kotlin, bao gồm hàm, câu lệnh if/else và tính chất rỗng

Kiến thức bạn sẽ học được

  • Cách xác định hàm bằng cú pháp lambda.
  • Cách lưu trữ hàm trong biến.
  • Cách truyền hàm ở dạng đối số cho hàm khác.
  • Cách trả về hàm từ hàm khác.
  • Cách dùng các loại hàm có thể có giá trị rỗng (nullable).
  • Cách làm biểu thức lambda ngắn gọn hơn.
  • Khái niệm hàm bậc cao.
  • Cách sử dụng hàm repeat().

Bạn cần có

  • Một trình duyệt web có quyền truy cập vào Kotlin Playground

2. Xem video tập lập trình (Không bắt buộc)

Nếu bạn muốn xem một trong những người hướng dẫn của khoá học hoàn thành lớp học lập trình, hãy phát video bên dưới.

Bạn nên mở rộng video ra toàn màn hình (có biểu tượng Biểu tượng này cho thấy 4 góc trên một hình vuông được làm nổi bật, để biểu thị chế độ toàn màn hình. ở góc của video) để có thể thấy Kotlin Playground và đoạn mã rõ hơn.

Bước này là bước không bắt buộc. Bạn cũng có thể bỏ qua video này và bắt đầu tham gia lớp học lập trình ngay.

3. Lưu trữ hàm trong biến

Tới đây, bạn đã học cách khai báo hàm bằng từ khoá fun. Có thể gọi một hàm được khai báo bằng từ khoá fun khiến mã trong nội dung hàm thực thi.

Hàm vừa là cấu trúc lớp thứ nhất vừa là loại dữ liệu, do đó bạn có thể lưu trữ hàm trong biến, truyền chúng vào hàm và trả về chúng từ hàm. Có thể bạn muốn thay đổi hành vi của một phần ứng dụng vào thời gian chạy hoặc lồng các hàm có khả năng kết hợp để tạo bố cục như bạn đã làm trong các lớp học lập trình trước. Tất cả những điều này có thể thực hiện được nhờ biểu thức lambda.

Bạn có thể thấy tính năng này trong thực tế với một số hành vi cho kẹo hay bị ghẹo. Đây là truyền thống Halloween ở nhiều quốc gia, trẻ em hoá trang rồi đến từng nhà và hỏi: "Cho kẹo hay bị ghẹo", thường thì sẽ được cho kẹo.

Lưu trữ hàm trong biến:

  1. Chuyển đến Kotlin Playground.
  2. Sau hàm main(), xác định một hàm trick() không có tham số và không có giá trị trả về để in "No treats!". Cú pháp giống như cú pháp của các hàm khác mà bạn thấy trong các lớp học lập trình trước.
fun main() {

}

fun trick() {
    println("No treats!")
}
  1. Trong phần nội dung của hàm main(), tạo một biến có tên là trickFunction và đặt biến đó bằng trick. Bạn không đưa dấu ngoặc đơn vào sau trick vì bạn muốn lưu trữ hàm trong biến, chứ không gọi hàm.
fun main() {
    val trickFunction = trick
}

fun trick() {
    println("No treats!")
}
  1. Chạy mã. Có lỗi vì trình biên dịch Kotlin nhận dạng trick là tên của hàm trick(), nhưng lại chờ bạn gọi hàm thay vì chỉ định hàm cho một biến.
Function invocation 'trick()' expected

Bạn cố gắng lưu trữ trick trong biến trickFunction. Tuy nhiên, để đặt hàm là một giá trị, bạn cần phải sử dụng toán tử tham chiếu hàm (::). Cú pháp được minh hoạ trong hình ảnh này:

a9a9bfa88485ec67.png

  1. Để đặt hàm là một giá trị, hãy chỉ định lại trickFunction cho ::trick.
fun main() {
    val trickFunction = ::trick
}

fun trick() {
    println("No treats!")
}
  1. Chạy mã để xác minh rằng không có lỗi nào khác. Bạn thấy cảnh báo trickFunction không bao giờ được sử dụng, nhưng đã được khắc phục trong phần tiếp theo.

Xác định lại hàm bằng biểu thức lambda

Biểu thức lambda cung cấp cú pháp ngắn gọn để xác định hàm không có từ khoá fun. Bạn có thể lưu trữ biểu thức lambda trực tiếp trong biến mà không cần tham chiếu hàm trên hàm khác.

Trước toán tử chỉ định (=), bạn thêm từ khoá val hoặc var, theo sau là tên biến (tên bạn sử dụng khi gọi hàm). Sau toán tử chỉ định (=) là biểu thức lambda, bao gồm một cặp dấu ngoặc nhọn tạo thành nội dung hàm. Cú pháp được minh hoạ trong hình ảnh này:

5e25af769cc200bc.png

Khi xác định hàm bằng biểu thức lambda, bạn có một biến tham chiếu đến hàm. Bạn cũng có thể chỉ định giá trị của biến đó cho biến khác như mọi loại khác và gọi hàm bằng tên của biến mới.

Cập nhật mã để sử dụng biểu thức lambda:

  1. Viết lại hàm trick() bằng biểu thức lambda. Tên trick nay tham chiếu đến tên của một biến. Phần nội dung hàm trong dấu ngoặc nhọn hiện là một biểu thức lambda.
fun main() {
    val trickFunction = ::trick
}

val trick = {
    println("No treats!")
}
  1. Trong hàm main(), hãy xoá toán tử tham chiếu hàm (::) vì trick nay tham chiếu đến một biến chứ không phải tên hàm.
fun main() {
    val trickFunction = trick
}

val trick = {
    println("No treats!")
}
  1. Chạy mã. Không có lỗi nào và bạn có thể tham chiếu đến hàm trick() không có toán tử tham chiếu hàm (::). Không có kết quả vì bạn vẫn chưa gọi hàm.
  2. Trong hàm main(), hãy gọi hàm trick(), nhưng lần này bao gồm dấu ngoặc đơn giống như khi bạn gọi bất kỳ hàm nào khác.
fun main() {
    val trickFunction = trick
    trick()
}

val trick = {
    println("No treats!")
}
  1. Chạy mã. Phần nội dung của biểu thức lambda được thực thi.
No treats!
  1. Trong hàm main(), hãy gọi biến trickFunction như thể đó là một hàm.
fun main() {
    val trickFunction = trick
    trick()
    trickFunction()
}

val trick = {
    println("No treats!")
}
  1. Chạy mã. Hàm được gọi hai lần, lần thứ nhất cho lệnh gọi hàm trick() và lần thứ hai cho lệnh gọi hàm trickFunction().
No treats!
No treats!

Với biểu thức lambda, bạn có thể tạo các biến lưu trữ hàm, gọi các biến này như hàm và lưu trữ chúng trong biến khác mà bạn có thể gọi như hàm.

4. Dùng hàm làm loại dữ liệu

Trong lớp học lập trình trước, bạn đã biết rằng Kotlin có suy luận loại dữ liệu. Khi khai báo một biến, thường thì bạn không cần chỉ định rõ loại. Trong ví dụ trước, trình biên dịch Kotlin có thể suy luận rằng giá trị của trick là một hàm. Tuy nhiên, nếu muốn chỉ định loại tham số hàm hoặc loại dữ liệu trả về, bạn cần biết cú pháp để thể hiện loại hàm. Loại hàm bao gồm một nhóm ngoặc đơn chứa danh sách tham số tuỳ chọn, ký hiệu -> và loại dữ liệu trả về. Cú pháp được minh hoạ trong hình ảnh này:

5608ac5e471b424b.png

Loại dữ liệu của biến trick mà bạn đã khai báo trước đó sẽ là () -> Unit. Dấu ngoặc đơn trống vì hàm không có tham số nào. Loại dữ liệu trả về là Unit vì hàm không trả về dữ liệu nào. Nếu bạn có một hàm nhận hai tham số Int và trả về một Int, thì loại dữ liệu của hàm đó sẽ là (Int, Int) -> Int.

Khai báo một hàm khác bằng biểu thức lambda chỉ định rõ loại hàm:

  1. Sau biến trick, khai báo một biến có tên là treat bằng với biểu thức lambda có phần nội dung in "Have a treat!".
val trick = {
    println("No treats!")
}

val treat = {
    println("Have a treat!")
}
  1. Chỉ định loại dữ liệu của biến treat() -> Unit.
val treat: () -> Unit = {
    println("Have a treat!")
}
  1. Trong hàm main(), hãy gọi hàm treat().
fun main() {
    val trickFunction = trick
    trick()
    trickFunction()
    treat()
}
  1. Chạy mã. Hàm treat() hoạt động giống như hàm trick(). Cả hai biến đều có cùng loại dữ liệu mặc dù chỉ có biến treat khai báo rõ.
No treats!
No treats!
Have a treat!

Dùng hàm làm loại dữ liệu trả về

Hàm là loại dữ liệu, vì vậy bạn có thể dùng hàm như bất kỳ loại dữ liệu nào khác. Thậm chí bạn có thể trả về hàm từ hàm khác. Cú pháp được minh hoạ trong hình ảnh này:

f16dd6ca0c1588f5.png

Tạo một hàm trả về một hàm.

  1. Xoá mã khỏi hàm main().
fun main() {

}
  1. Sau hàm main(), xác định một hàm trickOrTreat() chấp nhận tham số isTrick thuộc loại Boolean.
fun main() {

}

fun trickOrTreat(isTrick: Boolean): () -> Unit {
}

val trick = {
    println("No treats!")
}

val treat = {
    println("Have a treat!")
}
  1. Trong phần nội dung của hàm trickOrTreat(), thêm một câu lệnh if trả về hàm trick() nếu isTricktrue và trả về hàm treat() nếu hàm isTrick là sai (false).
fun trickOrTreat(isTrick: Boolean): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        return treat
    }
}
  1. Trong hàm main(), tạo một biến có tên là treatFunction rồi chỉ định biến đó cho kết quả của lệnh gọi trickOrTreat(), truyền vào false cho tham số isTrick. Sau đó, tạo một biến thứ hai, được gọi là trickFunction, rồi chỉ định biến đó cho kết quả của lệnh gọi trickOrTreat(), lần này truyền vào true cho tham số isTrick.
fun main() {
    val treatFunction = trickOrTreat(false)
    val trickFunction = trickOrTreat(true)
}
  1. Gọi treatFunction() rồi gọi trickFunction() ở dòng tiếp theo.
fun main() {
    val treatFunction = trickOrTreat(false)
    val trickFunction = trickOrTreat(true)
    treatFunction()
    trickFunction()
}
  1. Chạy mã. Bạn sẽ thấy kết quả cho từng hàm. Mặc dù không gọi trực tiếp hàm trick() hoặc treat(), nhưng bạn vẫn có thể gọi các hàm này vì bạn đã lưu trữ các giá trị trả về từ mỗi lần bạn gọi hàm trickOrTreat() và gọi các hàm có biến trickFunctiontreatFunction.
Have a treat!
No treats!

Giờ đây, bạn đã biết cách hàm có thể trả về hàm khác. Bạn cũng có thể truyền một hàm ở dạng đối số cho một hàm khác. Có thể bạn muốn cung cấp một số hành vi tuỳ chỉnh cho hàm trickOrTreat() để thực hiện lệnh khác ngoài lệnh trả về một trong hai chuỗi. Hàm nhận một hàm khác làm đối số cho phép bạn truyền một hàm khác mỗi lần được gọi.

Truyền hàm vào hàm khác làm đối số

Ở một số nơi trên thế giới có ngày lễ Halloween, trẻ em sẽ được cho tiền lẻ thay vì kẹo hoặc được cho cả hai. Bạn sẽ sửa đổi hàm trickOrTreat() để cho phép một phiên bản khác (được biểu thị bằng một hàm) được cung cấp làm đối số.

Hàm mà trickOrTreat() sử dụng làm tham số cũng cần nhận một tham số của riêng mình. Khi khai báo loại hàm, tham số không được gắn nhãn. Bạn chỉ cần chỉ định loại dữ liệu của từng tham số (phân tách bằng dấu phẩy). Cú pháp được minh hoạ trong hình ảnh này:

8372d3b83d539fac.png

Khi bạn viết biểu thức lambda cho hàm nhận tham số, tham số sẽ được đặt tên theo thứ tự xuất hiện. Tên tham số được liệt kê sau dấu ngoặc nhọn mở và mỗi tên được phân tách bằng dấu phẩy. Mũi tên (->) phân tách các tên tham số khỏi phần nội dung hàm. Cú pháp được minh hoạ trong hình ảnh này:

938d2adf25172873.png

Cập nhật hàm trickOrTreat() để lấy hàm làm tham số:

  1. Sau tham số isTrick, thêm một tham số extraTreat thuộc loại (Int) -> String.
fun trickOrTreat(isTrick: Boolean, extraTreat: (Int) -> String): () -> Unit {
  1. Trong khối else, trước câu lệnh return, gọi println(), truyền một lệnh gọi đến hàm extraTreat(). Truyền 5 vào lệnh gọi đến extraTreat().
fun trickOrTreat(isTrick: Boolean, extraTreat: (Int) -> String): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        println(extraTreat(5))
        return treat
    }
}
  1. Bây giờ, khi gọi hàm trickOrTreat(), bạn cần xác định một hàm bằng biểu thức lambda và truyền vào cho tham số extraTreat. Trong hàm main() trước khi thực hiện lệnh gọi đến hàm trickOrTreat(), thêm một hàm coins(). Hàm coins() đặt cho tham số Int tên quantity và trả về một String. Bạn có thể thấy không có từ khoá return. Bạn không thể sử dụng từ khoá này trong biểu thức lambda. Thay vào đó, kết quả của biểu thức cuối cùng trong hàm sẽ trở thành giá trị trả về.
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }

    val treatFunction = trickOrTreat(false)
    val trickFunction = trickOrTreat(true)
    treatFunction()
    trickFunction()
}
  1. Sau hàm coins(), thêm một hàm cupcake() như ví dụ dưới đây. Đặt tên cho số lượng tham số Int quantity và tách khỏi phần nội dung hàm bằng toán tử ->. Bây giờ, bạn có thể truyền hàm coins() hoặc cupcake() vào hàm trickOrTreat().
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }

    val cupcake: (Int) -> String = { quantity ->
        "Have a cupcake!"
    }

    val treatFunction = trickOrTreat(false)
    val trickFunction = trickOrTreat(true)
    treatFunction()
    trickFunction()
}
  1. Trong hàm cupcake(), hãy xoá tham số quantity và biểu tượng ->. Tham số và biểu tượng này không được sử dụng nên có thể bỏ qua được.
val cupcake: (Int) -> String = {
    "Have a cupcake!"
}
  1. Cập nhật lệnh gọi thành hàm trickOrTreat(). Đối với lệnh gọi thứ nhất, khi isTrickfalse, truyền vào hàm coins(). Đối với lệnh gọi thứ hai, khi isTricktrue, truyền vào hàm cupcake().
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }

    val cupcake: (Int) -> String = {
        "Have a cupcake!"
    }

    val treatFunction = trickOrTreat(false, coins)
    val trickFunction = trickOrTreat(true, cupcake)
    treatFunction()
    trickFunction()
}
  1. Chạy mã. Hàm extraTreat() chỉ được gọi khi tham số isTrick được đặt thành đối số false, do đó, kết quả sẽ bao gồm 5 đồng 25 xu nhưng không có bánh.
5 quarters
Have a treat!
No treats!

Loại hàm có thể có giá trị rỗng (nullable)

Giống như các loại dữ liệu khác, loại hàm có thể được khai báo là có thể có giá trị rỗng. Trong những trường hợp này, biến có thể chứa hàm hoặc có thể là null.

Để khai báo một hàm là có thể có giá trị rỗng, hãy đưa loại hàm vào trong ngoặc đơn, theo sau là biểu tượng ? bên ngoài ngoặc đơn kết thúc. Ví dụ: nếu bạn muốn đặt loại () -> String là có thể có giá trị rỗng, khai báo loại này là loại (() -> String)?. Cú pháp được minh hoạ trong hình ảnh này:

c8a004fbdc7469d.png

Đặt tham số extraTreat là có thể có giá trị rỗng để bạn không phải cung cấp hàm extraTreat() mỗi khi bạn gọi hàm trickOrTreat():

  1. Thay đổi loại của tham số extraTreat thành (() -> String)?.
fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
  1. Sửa đổi lệnh gọi hàm extraTreat() để sử dụng câu lệnh if nhằm chỉ gọi hàm nếu hàm đó không có giá trị rỗng (non-null). Hàm trickOrTreat() giờ đây sẽ có dạng như đoạn mã này:
fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        if (extraTreat != null) {
            println(extraTreat(5))
        }
        return treat
    }
}
  1. Xoá hàm cupcake(), sau đó thay đối số cupcake bằng null trong lệnh gọi thứ hai đến hàm trickOrTreat().
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }

    val treatFunction = trickOrTreat(false, coins)
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}
  1. Chạy mã. Kết quả sẽ không thay đổi. Bây giờ, bạn có thể khai báo các loại hàm là có thể có giá trị rỗng, bạn không cần phải truyền hàm cho tham số extraTreat nữa.
5 quarters
Have a treat!
No treats!

5. Viết biểu thức lambda với cú pháp viết tắt

Biểu thức lambda cung cấp nhiều cách để làm cho mã ngắn gọn hơn. Bạn sẽ tìm hiểu một số cách trong phần này vì hầu hết biểu thức lambda mà bạn gặp và viết đều được viết bằng cú pháp viết tắt.

Bỏ qua tên của tham số

Khi viết hàm coins(), bạn đã khai báo rõ tên quantity cho tham số Int của hàm đó. Tuy nhiên, như bạn thấy với hàm cupcake(), bạn có thể hoàn toàn bỏ qua tên tham số. Khi hàm có một tham số và bạn không cung cấp tên, Kotlin sẽ ngầm chỉ định tên it cho tham số đó, vì vậy bạn có thể bỏ qua tên tham số và biểu tượng ->, nhờ vậy biểu thức lambda ngắn gọn hơn. Cú pháp được minh hoạ trong hình ảnh này:

332ea7bade5062d6.png

Cập nhật hàm coins() để sử dụng cú pháp viết tắt cho tham số:

  1. Trong hàm coins(), hãy xoá tên tham số quantity và biểu tượng ->.
val coins: (Int) -> String = {
    "$quantity quarters"
}
  1. Thay đổi mẫu chuỗi "$quantity quarters" để tham chiếu đến một tham số sử dụng $it.
val coins: (Int) -> String = {
    "$it quarters"
}
  1. Chạy mã. Kotlin nhận dạng tên tham số it của tham số Int và vẫn in số đồng 25 xu.
5 quarters
Have a treat!
No treats!

Truyền trực tiếp biểu thức lambda vào hàm

Hàm coins() hiện chỉ được dùng ở một nơi. Điều gì xảy ra nếu bạn chỉ cần truyền biểu thức lambda trực tiếp vào hàm trickOrTreat() mà không cần tạo biến trước?

Biểu thức lambda chỉ đơn giản là giá trị cố định của hàm, giống như 0 là một giá trị cố định dạng số nguyên hoặc "Hello" là một giá trị cố định dạng chuỗi. Bạn có thể truyền trực tiếp biểu thức lambda vào lệnh gọi hàm. Cú pháp được minh hoạ trong hình ảnh này:

39dc1086e2471ffc.png

Sửa đổi mã để bạn có thể xoá biến coins:

  1. Di chuyển biểu thức lambda để biểu thức này truyền trực tiếp vào lệnh gọi đến hàm trickOrTreat(). Bạn cũng có thể gộp biểu thức lambda vào một dòng.
fun main() {
    val coins: (Int) -> String = {
        "$it quarters"
    }
    val treatFunction = trickOrTreat(false, { "$it quarters" })
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}
  1. Xoá biến coins vì biến này không còn được sử dụng nữa.
fun main() {
    val treatFunction = trickOrTreat(false, { "$it quarters" })
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}
  1. Chạy mã. Mã vẫn biên dịch và chạy như dự kiến.
5 quarters
Have a treat!
No treats!

Sử dụng cú pháp lambda ở cuối

Bạn có thể dùng một cách viết tắt khác để viết biểu thức lambda khi loại hàm là tham số cuối cùng của một hàm. Nếu vậy, bạn có thể đặt biểu thức lambda sau ngoặc đơn đóng để gọi hàm. Cú pháp được minh hoạ trong hình ảnh này:

3ee3176d612b54.png

Điều này giúp mã của bạn dễ đọc hơn vì tách biệt biểu thức lambda với các tham số khác, nhưng không thay đổi tính chất của mã.

Cập nhật mã để sử dụng cú pháp lambda ở cuối:

  1. Trong biến treatFunction, di chuyển biểu thức lambda {"$it quarters"} sau ngoặc đơn đóng trong lệnh gọi đến trickOrTreat().
val treatFunction = trickOrTreat(false) { "$it quarters" }
  1. Chạy mã. Mọi thứ vẫn hoạt động!
5 quarters
Have a treat!
No treats!

6. Dùng hàm repeat()

Khi một hàm trả về một hàm hoặc nhận hàm làm đối số, hàm này được gọi là hàm bậc cao. Hàm trickOrTreat() là ví dụ về hàm bậc cao vì hàm này nhận một hàm thuộc loại ((Int) -> String)? làm tham số và trả về một hàm thuộc loại () -> Unit. Kotlin cung cấp một số hàm bậc cao hữu ích mà bạn có thể tận dụng bằng kiến thức mới học về hàm lambda.

Hàm repeat() là một hàm bậc cao như vậy. Hàm repeat() là một cách ngắn gọn để thể hiện vòng lặp for bằng hàm. Bạn sử dụng hàm này và các hàm bậc cao thường xuyên trong các bài học sau. Hàm repeat() có chữ ký hàm này:

repeat(times: Int, action: (Int) -> Unit)

Tham số times là số lần hành động sẽ xảy ra. Tham số action là một hàm nhận một tham số Int và trả về một loại Unit. Tham số Int của hàm action là số lần hành động đã thực thi cho đến nay, chẳng hạn như đối số 0 cho lần lặp lại thứ nhất hoặc đối số 1 cho lần lặp lại thứ hai. Bạn có thể dùng hàm repeat() để lặp lại mã một số lần định trước, tương tự như vòng lặp for. Cú pháp được minh hoạ trong hình ảnh này:

519a2e0f5d02687.png

Thay vì chỉ gọi hàm trickFunction() một lần, bạn có thể gọi hàm này nhiều lần bằng hàm repeat().

Cập nhật mã cho kẹo hay bị ghẹo để xem hàm repeat() hoạt động:

  1. Trong hàm main(), gọi hàm repeat() ở giữa các lệnh gọi đến treatFunction()trickFunction(). Truyền vào 4 cho tham số times và sử dụng cú pháp lambda ở cuối cho hàm action. Bạn không cần cung cấp tên cho tham số Int của biểu thức lambda.
fun main() {
    val treatFunction = trickOrTreat(false) { "$it quarters" }
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
    repeat(4) {

    }
}
  1. Di chuyển lệnh gọi đến hàm treatFunction() vào biểu thức lambda của hàm repeat().
fun main() {
    val treatFunction = trickOrTreat(false) { "$it quarters" }
    val trickFunction = trickOrTreat(true, null)
    repeat(4) {
        treatFunction()
    }
    trickFunction()
}
  1. Chạy mã. Chuỗi "Have a treat" phải in bốn lần.
5 quarters
Have a treat!
Have a treat!
Have a treat!
Have a treat!
No treats!

7. Kết luận

Xin chúc mừng! Bạn đã tìm hiểu kiến thức cơ bản về loại hàm và biểu thức lambda. Làm quen với các khái niệm này sẽ giúp bạn tìm hiểu thêm về ngôn ngữ Kotlin. Việc sử dụng loại hàm, hàm bậc cao và cú pháp viết tắt cũng giúp mã ngắn gọn và dễ đọc hơn.

Tóm tắt

  • Hàm trong Kotlin là cấu trúc lớp thứ nhất và có thể được coi như loại dữ liệu.
  • Biểu thức lambda cung cấp cú pháp viết tắt để viết hàm.
  • Bạn có thể truyền loại hàm vào hàm khác.
  • Bạn có thể trả về loại hàm từ một hàm khác.
  • Biểu thức lambda trả về giá trị của biểu thức cuối cùng.
  • Nếu một nhãn tham số bị bỏ qua trong biểu thức lambda có một tham số, thì nhãn này sẽ được tham chiếu bằng giá trị nhận dạng it.
  • Bạn có thể viết biểu thức lambda cùng dòng mà không cần tên biến.
  • Nếu tham số cuối cùng của một hàm là loại hàm, bạn có thể dùng cú pháp lambda ở cuối để di chuyển biểu thức lambda sau ngoặc đơn cuối cùng khi gọi hàm.
  • Hàm bậc cao là hàm nhận hàm khác làm tham số hoặc trả về hàm.
  • Hàm repeat() là một hàm bậc cao hoạt động tương tự như vòng lặp for.

Tìm hiểu thêm