Function
ฟังก์ชั่น
การประกาศฟังก์ชั่นใน Swift จะมีหน้าตาประมาณนี้
func greet(person: String) -> String {
return "Hello, " + person + "!"
}
เริ่มด้วย keyword func
จากนั้นเป็นชื่อฟังก์ชั่น ตัวอย่างนี้คือ greet
จากนั้นจะเป็นวงเล็บ ในวงเล็บจะเป็น argument ที่จะส่งให้กับฟังก์ชั่น ถ้าฟังก์ชั่นให้ผลลัพธ์ออกมา จะตามด้วยเครื่องหมาย ->
แล้วตามด้วย Type ของผลลัพธ์จากฟังก์ชั่น
ในฟังก์ชั่น เราใช้ keyword return
ในการคืนผลลัพธ์ออกจากฟังก์ชั่น
วิธีการเรียกใช้
let greetingMessage = greet(person: "pop")
ผลลัพธ์เก็บใน greetingMessage
จากการเรียกฟังก์ชั่น greet
ส่ง "Pop"
เป็น input argument person ของฟังก์ชั่น
โดยปกติเวลาเขียน function signature แบบย่อ ๆ ของฟังก์ชั่นนี้เราจะเขียนได้ ประมาณนี้ greet(person:)
ฟังก์ชั่นสามารถส่งออกผลลัพธ์ได้แค่ Type เดียว ถ้าต้องการหลายผลลัพธ์เราอาจใช้ Tuple ช่วยได้แบบนี้
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
ฟังก์ชั่นในภาษา Swift สามารถมีชื่อตัวแปรได้สองชื่อต่อหนึ่งตัว นั่นคือ
Argument label เป็น label ตอนเรียกใช้งานจากภายนอกฟังก์ชั่น
Parameter name ใช้งานภายในฟังก์ชั่น
(ในกรณีที่มีชื่อเดียว จะทำหน้าที่เป็นทั้ง argument label และ parameter name แบบฟังก์ชั่นที่เราเขียนกันไปแล้ว)
หน้าตาจะประมาณนี้
func someFunction(argumentLabel parameterName: Int) {
}
เช่น
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! from \(hometown)."
}
จะเห็นว่า argument ที่สองของฟังก์ชั่นมี argument label ว่า from
และมี parameter name ว่า hometown
เวลาเรียกฟังก์ชั่นจากภายนอกจะเป็นแบบนี้
greet(person: "John", from: "Bangkok")
ทำให้เราอ่านแล้วลื่นไหล ทั้งจากโค้ดที่เรียกฟังก์ชั่นและโค้ดที่อยู่ในฟังก์ชั่น เพราะบริบทต่างกัน
ในบางกรณีเราต้องการให้เรียกโดยไม่ต้องระบุ label ให้เรากำหนด argument label เป็น _
แทน เช่น
func append(_ item: String) {
}
append("Pop")
เราสามารถกำหนด default value ให้กับ argument ได้โดยการกำหนดค่าในตอนประกาศฟังก์ชั่นแบบนี้
func displayItem(name: String, isDone: Bool = false) {
print("Item name: \(name), isDone: \(isDone)")
}
displayItem(name: "Learn DDD", isDone: true)
displayItem(name: "Learn iOS")
จะเห็นว่าเมื่อเรากำหนด default ให้แล้ว เราสามารถละการส่ง argument นั้นได้ตอนเรียกใช้ฟังก์ชั่น
ฟังก์ชั่นใน Swift ก็เป็น Type
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! from \(hometown)."
}
ฟังก์ชั่นนี้จะมี type เป็นแบบนี้
(String, String) -> String
เนื่องจากฟังก์ชั่นใน Swift เป็น Type เราสามารถประกาศตัวแปรที่มี Type เป็น function ได้ เช่น
var hello: (String, String) -> String = greet
hello("Pop", "Bangkok")
และด้วยความที่ฟังก์ชั่นก็เป็น Type ทำให้เราสามารถส่ง ฟังก์ชั่นเป็น input ของฟังก์ชั่นได้ด้วย เช่น
func download(url: String, completion: (String) -> ()) {
completion(url)
}
func display(text: String) {
print(text)
}
download(url: "mock.com", completion:display)
รวมทั้งคืนผลลัพธ์เป็นฟังก์ชั่นด้วย แบบนี้
func greeting(prefix: String) -> (String) -> () {
func greet(name: String) {
print("\(prefix) \(name)")
}
return greet
}
greeting(prefix: "hello")("Pop")
greeting(prefix: "hello")("John")
Closure
ถ้าอธิบายแบบง่าย ๆ คือ ฟังก์ชั่นคือ closure ที่มีชื่อ หรือก็คือ closure เป็น block ของโค้ดที่ไม่มีการประกาศชื่อนั่นเอง ตัวอย่างเช่น
func greeting(prefix: String) -> (String) -> () {
return { name in
print("\(prefix) \(name)")
}
}
Closure คือส่วนนี้ เนื่องจาก greeting ได้ระบุ Type ของผลลัพธ์ไว้แล้วทำให้ name ใน closure สามารถ infer type เป็น String
{ name in
print("\(prefix) \(name)")
}
การลดรูปการเรียกใช้ฟังก์ชั่น ในกรณีที่ input เป็นฟังก์ชั่น
ตัวอย่างเช่น การเรียกฟังก์ชั่น index ของ array เพื่อหา index ของ item แรกที่ตรงกับเงื่อนไขที่ระบุ
ฟังก์ชั่นรับ input เป็นฟังก์ชั่นในการหา โดยวนเรียกฟังก์ชั่นนี้กับทีละ item ใน array โดยที่ถ้า item ไหนทำให้ฟังก์ชั่นที่เป็น input นี้ได้ผลลัพธ์เป็น true
firstIndex จะให้ผลลัพธ์เป็น Index ของ item นั้น
items.firstIndex(where: { (item) -> Bool in
item == "water"
})
เริ่มลดรูปจากการตัด -> Bool
ออก เนื่องจากเรารู้จากฟังก์ชั่น firstIndex แล้วว่าต้องรับ ฟังก์ชั่นที่ return Bool
items.firstIndex(where: { (item) in
item == "water"
})
ตัด (item) in ออกแทนที่ parameter แรกที่รับ ด้วย $0
items.firstIndex(where: { $0 == "water" })
ตัด (where: ) ออก parameter สุดท้ายถ้ารับเป็นฟังก์ชั่น สามารถละได้
items.firstIndex { $0 == "water" }
Last updated