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 ở 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:
- Chuyển đến Kotlin Playground.
- Sau hàm
main()
, xác định một hàmtrick()
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!")
}
- 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ằngtrick
. Bạn không đưa dấu ngoặc đơn vào sautrick
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!")
}
- 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àmtrick()
, 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:
- Để đặ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!")
}
- 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:
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:
- Viết lại hàm
trick()
bằng biểu thức lambda. Têntrick
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!")
}
- 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!")
}
- 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. - Trong hàm
main()
, hãy gọi hàmtrick()
, 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!")
}
- Chạy mã. Phần nội dung của biểu thức lambda được thực thi.
No treats!
- Trong hàm
main()
, hãy gọi biếntrickFunction
như thể đó là một hàm.
fun main() {
val trickFunction = trick
trick()
trickFunction()
}
val trick = {
println("No treats!")
}
- 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àmtrickFunction()
.
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:
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:
- 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!")
}
- Chỉ định loại dữ liệu của biến
treat
là() -> Unit
.
val treat: () -> Unit = {
println("Have a treat!")
}
- Trong hàm
main()
, hãy gọi hàmtreat()
.
fun main() {
val trickFunction = trick
trick()
trickFunction()
treat()
}
- Chạy mã. Hàm
treat()
hoạt động giống như hàmtrick()
. Cả hai biến đều có cùng loại dữ liệu mặc dù chỉ có biếntreat
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:
Tạo một hàm trả về một hàm.
- Xoá mã khỏi hàm
main()
.
fun main() {
}
- Sau hàm
main()
, xác định một hàmtrickOrTreat()
chấp nhận tham sốisTrick
thuộc loạiBoolean
.
fun main() {
}
fun trickOrTreat(isTrick: Boolean): () -> Unit {
}
val trick = {
println("No treats!")
}
val treat = {
println("Have a treat!")
}
- Trong phần nội dung của hàm
trickOrTreat()
, thêm một câu lệnhif
trả về hàmtrick()
nếuisTrick
làtrue
và trả về hàmtreat()
nếu hàmisTrick
là sai (false).
fun trickOrTreat(isTrick: Boolean): () -> Unit {
if (isTrick) {
return trick
} else {
return treat
}
}
- 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ọitrickOrTreat()
, truyền vàofalse
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ọitrickOrTreat()
, lần này truyền vàotrue
cho tham sốisTrick
.
fun main() {
val treatFunction = trickOrTreat(false)
val trickFunction = trickOrTreat(true)
}
- Gọi
treatFunction()
rồi gọitrickFunction()
ở dòng tiếp theo.
fun main() {
val treatFunction = trickOrTreat(false)
val trickFunction = trickOrTreat(true)
treatFunction()
trickFunction()
}
- 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ặctreat()
, 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àmtrickOrTreat()
và gọi các hàm có biếntrickFunction
vàtreatFunction
.
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:
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:
Cập nhật hàm trickOrTreat()
để lấy hàm làm tham số:
- 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 {
- Trong khối
else
, trước câu lệnhreturn
, gọiprintln()
, truyền một lệnh gọi đến hàmextraTreat()
. Truyền5
vào lệnh gọi đếnextraTreat()
.
fun trickOrTreat(isTrick: Boolean, extraTreat: (Int) -> String): () -> Unit {
if (isTrick) {
return trick
} else {
println(extraTreat(5))
return treat
}
}
- 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àmmain()
trước khi thực hiện lệnh gọi đến hàmtrickOrTreat()
, thêm một hàmcoins()
. Hàmcoins()
đặt cho tham sốInt
tênquantity
và trả về mộtString
. 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()
}
- Sau hàm
coins()
, thêm một hàmcupcake()
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àmcoins()
hoặccupcake()
vào hàmtrickOrTreat()
.
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()
}
- 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!"
}
- Cập nhật lệnh gọi thành hàm
trickOrTreat()
. Đối với lệnh gọi thứ nhất, khiisTrick
làfalse
, truyền vào hàmcoins()
. Đối với lệnh gọi thứ hai, khiisTrick
làtrue
, truyền vào hàmcupcake()
.
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()
}
- 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:
Đặ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()
:
- Thay đổi loại của tham số
extraTreat
thành(() -> String)?
.
fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
- Sửa đổi lệnh gọi hàm
extraTreat()
để sử dụng câu lệnhif
nhằm chỉ gọi hàm nếu hàm đó không có giá trị rỗng (non-null). HàmtrickOrTreat()
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
}
}
- Xoá hàm
cupcake()
, sau đó thay đối sốcupcake
bằngnull
trong lệnh gọi thứ hai đến hàmtrickOrTreat()
.
fun main() {
val coins: (Int) -> String = { quantity ->
"$quantity quarters"
}
val treatFunction = trickOrTreat(false, coins)
val trickFunction = trickOrTreat(true, null)
treatFunction()
trickFunction()
}
- 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:
Cập nhật hàm coins()
để sử dụng cú pháp viết tắt cho tham số:
- Trong hàm
coins()
, hãy xoá tên tham sốquantity
và biểu tượng->
.
val coins: (Int) -> String = {
"$quantity quarters"
}
- 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"
}
- 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:
Sửa đổi mã để bạn có thể xoá biến coins
:
- 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()
}
- 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()
}
- 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:
Đ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:
- Trong biến
treatFunction
, di chuyển biểu thức lambda{"$it quarters"}
sau ngoặc đơn đóng trong lệnh gọi đếntrickOrTreat()
.
val treatFunction = trickOrTreat(false) { "$it quarters" }
- 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:
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:
- Trong hàm
main()
, gọi hàmrepeat()
ở giữa các lệnh gọi đếntreatFunction()
vàtrickFunction()
. Truyền vào4
cho tham sốtimes
và sử dụng cú pháp lambda ở cuối cho hàmaction
. 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) {
}
}
- Di chuyển lệnh gọi đến hàm
treatFunction()
vào biểu thức lambda của hàmrepeat()
.
fun main() {
val treatFunction = trickOrTreat(false) { "$it quarters" }
val trickFunction = trickOrTreat(true, null)
repeat(4) {
treatFunction()
}
trickFunction()
}
- 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ặpfor
.