Function được hiểu là 1 khối code thực hiện 1 logic nào đó và có thể sử dụng lại.Khái niệm này tương tư như các ngôn ngữ khác.
Function trong Scala có thể được mô tả bằng 2 tính chất :
- Được đặt tên
- Là 1 hay nhiều expression có thể tái sử dụng.
Function trong scala mang nhiều đặc điểm của Functional programming,tuy nhiên trong bài này tôi sẽ không giải thích về Functional programming,nó sẽ là bài tập của bạn,kết thúc bài viết này bạn thử tìm hiểu về Functional programming và đối chiếu lại với những tính chất tôi liệt kê dưới đây.
Ví dụ :
Cách 2: Scala cung cấp cho bạn 1 giải pháp cho tình huống này :
Mỗi loại dữ liệu định nghĩa như 1 class và có những method đi kèm tương ứng.
Có rất nhiều method cho mỗi class data type và bài tập của các bạn hãy tìm hiểu thật nhiều những method đó trước khi ta đến với bài tiếp theo về First-Class Functions
Function trong Scala có thể được mô tả bằng 2 tính chất :
- Được đặt tên
- Là 1 hay nhiều expression có thể tái sử dụng.
Function trong scala mang nhiều đặc điểm của Functional programming,tuy nhiên trong bài này tôi sẽ không giải thích về Functional programming,nó sẽ là bài tập của bạn,kết thúc bài viết này bạn thử tìm hiểu về Functional programming và đối chiếu lại với những tính chất tôi liệt kê dưới đây.
I - Cách khai báo Function trong Scala
Input-less Function (không có input)
Syntax:
def <identifier> = <expression>Tương tự như bạn khai báo 1 value hay 1 variable ,bạn thấy có gì khác ở đây? chúng ta có từ khoá "def".
Ví dụ :
scala> def chaoHoai = "Chào Hoài PT"1 cách khác để bạn khai báo 1 function không có input đó là dùng 1 cặp dấu đóng mở tròn rỗng () - Empty Parentheses.Tôi viết lại function trên với Empty Parentheses :
chaoHoai: String
scala> chaoHoai
res0: String = Chào Hoài PT
scala> def chaoHoai2() = "Chào Hoài PT"Bạn thấy điều gì khác biệt ở kết quả không , điều đó dẫn điến viêc sử dụng cũng khác nhau :
chaoHoai2: ()String
scala> chaoHoai2()
res1: String = Chào Hoài PT
scala> chaoHoai2
res2: String = Chào Hoài PT
scala> chaoHoai()
<console>:12: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
chaoHoai()
^
Function with a Return Type (function trả về kiểu cố định)
Như bạn thấy ở trên ,nếu bạn không set kiểu trả về cho function Scala sẽ tự tính toán và set cho bạn, trong thực tế bạn nên tự set kiểu cho function mình viết, điều đấy khiến cho code của bạn rõ ràng hơn và tránh được nhiều sai sót ngoài ý muốn.
Syntax:
def <identifier>: <type> = <expression>Ví dụ :
scala> def kieuTraVeLaString : String = "đây là 1 String"
kieuTraVeLaString: String
scala> def kieuTraVeLaInt : Int = 100
kieuTraVeLaInt: Int
Định nghĩa đầy đủ 1 Function
Syntax:def <identifier>(<identifier>: <type>[, ... ]): <type> = <expression>Ví dụ :
scala> def cong2So(soThuNhat: Int , soThuHai: Int) : Int = soThuNhat + soThuHaiScala cho phép bạn gọi function với các input với tên được định nghĩa trước đó,ta thử gọi lại function trên với thứ tự input đảo ngược:
cong2So: (soThuNhat: Int, soThuHai: Int)Int
scala> cong2So(2,3)
res4: Int = 5
scala> cong2So(soThuHai = 3,soThuNhat = 2)
res5: Int = 5
Vararg Parameters
Đôi khi bạn định nghĩa 1 function với với input cùng kiểu và không biết rõ số lượng , Scala đồng ý bạn viết như sau :
scala> def tinhTongNhieuSo(cacSo: Int*): Int = {
| var tong = 0
| for (i <- cacSo) tong += i
| tong
| }
tinhTongNhieuSo: (cacSo: Int*)Int
scala> tinhTongNhieuSo(1,2,3)
res6: Int = 6
scala> tinhTongNhieuSo(5,10,15,20)
res7: Int = 50
Parameter Groups
Ngoài ra ta có 1 cách define biến khác trong scala, đó là tách thành nhiều group parameter
scala> def soNaoLon(soThuNhat: Int)(soThuHai: Int) = if(soThuNhat > soThuHai) soThuNhat else soThuHai
soNaoLon: (soThuNhat: Int)(soThuHai: Int)Int
scala> soNaoLon(3)(1)
res8: Int = 3
scala> soNaoLon(3)(5)
res9: Int = 5
Function Invocation with Expression Blocks
Theo cách thông thường ,bạn sẽ chuẩn bị trc input và sau đó gọi function .
Ví dụ ở đây tôi viết hàm kiểm tra 1 số là chẵn hay lẻ :
Ví dụ ở đây tôi viết hàm kiểm tra 1 số là chẵn hay lẻ :
scala> def chanHayLe(x : Int) {Giờ tôi sẽ cộng 2 số bất kì và kiểm tra xem số đó là chẵn hay lẻ:
| if (x % 2 == 0) println("so chan")
| else println("so le")
| }
chanHayLe: (x: Int)Unit
scala> val tong2SoBatKy = 5 + 9Với Scala mọi thứ đơn giản hơn 1 bước :
tong2SoBatKy: Int = 14
scala> chanHayLe(tong2SoBatKy)
so chan
scala> chanHayLe { 5 + 9}Ví dụ này đơn giản quá so với sự hữu ích của tính năng này,trước mắt tôi chỉ muốn giới thiêu cho bạn như vậy.
so chan
Function’s Type Parameters
Đôi khi bạn cần viết 1 function mà kiểu trả về là động , ví dụ bạn viết 1 function mà kiểu trả về tưởng ứng với kiểu input.
Cách 1 : bạn sử dụng Any vì Any là root của mọi data trong Scala như ta đã nói ở bài 1
scala> def anyThings(x : Any) : Any = xỞ đây anyThings của 1 không trả về 1 số Int vì qua hàm anyThings nó đã biến thành kiểu Any
anyThings: (x: Any)Any
scala> val soInt: Int = anyThings(1)<console>:11: error: type mismatch;found : Anyrequired: Intval soInt: Int = anyThings(1)^
Cách 2: Scala cung cấp cho bạn 1 giải pháp cho tình huống này :
scala> def anyThings[A](x : A) : A = x
anyThings: [A](x: A)A
scala> val soInt: Int = anyThings(1)
soInt: Int = 1
Nested Functions
Scala cho phép bạn khai báo function trong function :scala> def timSoLonTrong3So(soI: Int, soII: Int, soIII: Int) = {
| def timSoLonTrong2So(soI: Int, soII: Int) = if(soI > soII) soI else soII
| timSoLonTrong2So(soI,timSoLonTrong2So(soII,soIII))
| }
timSoLonTrong3So: (soI: Int, soII: Int, soIII: Int)Int
scala> timSoLonTrong3So(5,15,10)
res1: Int = 15
Procedures
Procedures là function mà không trả về giá trị gì cả hay đúng hơn nó trả về 1 Unit
scala> def procedure(ten: String) = println("chao "+ ten)
procedure: (ten: String)Unit
scala> procedure("HoaiPT")
chao HoaiPT
II - Methods and Operators
Khi bắt đầu làm quen với Scala bạn sẽ bắt gặp 1 số "function" như làm tròn 1 số Double hay kiểm trả kết thúc 1 chuỗi :
scala> val soDouble : Double = 1.5645
soDouble: Double = 1.5645
scala> soDouble.round
res6: Long = 2
scala> val tenToi : String = "HoaiPT"Như chúng ta đã tìm hiểu ở bài đầu tiên,mọi data trong scala đều là 1 class ,và những function mà bạn bắt gặp kia thực chất là method của class đó.
tenToi: String = HoaiPT
scala> tenToi.endsWith("PT")
res7: Boolean = true
Mỗi loại dữ liệu định nghĩa như 1 class và có những method đi kèm tương ứng.
Có rất nhiều method cho mỗi class data type và bài tập của các bạn hãy tìm hiểu thật nhiều những method đó trước khi ta đến với bài tiếp theo về First-Class Functions
Parameter Groups cái này là currying chứ bạn nhỉ
ReplyDeletevâng,nhưng mình muốn diễn giai nó theo hướng này vì cảm thấy đơn giản hiểu thế là đủ
Delete