إذا أزلنا كل الأسماء والتسميات من توقيع دالة Swift، فسيتبقى لنا نوع الدالة.
func shoppingList(item: String, quantity: Int) -> String {
"You need to buy \(quantity) \(item)."
}
// shoppingList: (String, Int) -> String
func repeater(_ phrase: String, times: Int) -> String {
var result = ""
for _ in 1...times {
result += phrase
}
return result
}
// repeater: (String, Int) -> String
func printString(line: String) {
print(line)
}
// printString: (String) -> ()
لاحِظ أن نوعي الدالتين الأولى والثانية متماثلان، (String, Int) -> String، رغم أن التوقيعين مختلفان وأن الدالتين تعملان بطريقتين مختلفتين تمامًا. فكلتاهما تأخذان String وInt كمدخل وتُرجعان String. وكما يتبين من نوع الدالة الثالثة، فرغم أن جسم الدالة لا يبدو أنه يُرجع أي شيء، فإنه في الواقع يُرجع () ضمنيًا، وهي القيمة الوحيدة من النوع Void.
يمكن استخدام أنواع الدوال هذه بالطريقة نفسها التي تُستخدم بها أي أنواع أخرى في Swift، فمثلًا يمكن استخدامها في تعريف المتغيرات أو الثوابت. وبما أن الدوال قيم في Swift، يمكن إسناد الدوال الموجودة بالفعل إلى هذه الثوابت/المتغيرات:
var stringAndIntToString: (String, Int) -> String
stringAndIntToString = shoppingList
stringAndIntToString("carrots", 3)
// => "You need to buy 3 carrots."
وكما هو الحال مع المتغيرات/الثوابت الأخرى، يجب أن تكون القيمة التي تُسندها من النوع الصحيح:
stringAndIntToString = printShoppingList
// Error: Cannot assign value of type '(String) -> ()' to type '(String, Int) -> String'
وبما أنه يمكن استخدام أنواع الدوال في أي مكان يمكن استخدام أنواع أخرى فيه، فإنه يترتب على ذلك أنه يمكن استخدامها كأنواع للمعاملات، وتمريرها إلى دوال أخرى، واستدعاؤها من داخل تلك الدوال.
func apply3(to str: String, function f: (String, Int) -> String) -> String {
f(str,3)
}
// apply3: ([String], (String, Int) -> String) -> [String]
apply3(to: "eggs", function: shoppingList)
// => "You need to buy 3 eggs."
apply3(to: "eggs", function: repeater)
// => "eggseggseggs"
وبالمثل، يمكن استخدام أنواع الدوال كأنواع للإرجاع في الدوال. بعبارة أخرى، يمكن كتابة دوال تُنشئ وتُرجع دوال أخرى. وعند إنشاء هذه الدوال، يمكن للدالة التي تُرجَع أن تستخدم المعاملات الأخرى الممرَّرة إلى الدالة أو المتغيرات المحلية المُنشأة داخل الدالة الأم.
func makeAdder(base: Int) -> (Int) -> Int {
func adder(_ i: Int) -> Int {
base + i
}
return adder
}
// makeAdder: (Int) -> (Int) -> Int
let add10 = makeAdder(base: 10)
// add10: (Int) -> Int
let subtract20 = makeAdder(base: -20)
// subtract10: (Int) -> Int
add10(5)
// => 15
subtract20(5)
// => -15
مرحبًا، أيها العميل Double-Null0111.
مهمتك، إن اخترت قبولها، هي كتابة أداتين تساعدانك على التسلل إلى مقر UMBRA (United Minions Being Really Awful) واستعادة مخططات أحدث خططهم الشنيعة. ستحتاج إلى أداتين لإنجاز هذه المهمة.
بعد حصولك على الخطط السرية، ستحتاج إلى حمايتها بحيث لا يتمكن من استعادتها إلا من يعرف كلمة المرور.
للقيام بذلك، ستحتاج إلى تنفيذ الدالة protectSecret(_ secret: String, withPassword password: String) -> (String) -> String.
ستُرجع هذه الدالة دالة أخرى تأخذ سلاسل نصية محتملة لكلمات المرور كمدخل.
إذا كانت كلمة المرور المُدخَلة صحيحة، تُرجع الدالة الجديدة السر المخفي، أما إذا كانت كلمة المرور غير صحيحة، فتُرجع الدالة "Sorry. No hidden secrets here."
let secretFunction = protectSecret("Steal the world's supply of french fries!", withPassword: "5up3r53cr37")
secretFunction("Open sesame")
// Returns "Sorry. No hidden secrets here."
secretFunction("5up3r53cr37")
// Returns "Steal the world's supply of french fries!"
علمنا أن UMBRA تبني جميع تركيبات خزائنها على رقم الغرفة التي تقع فيها. تُولَّد تركيبات الخزنة بتطبيق دالة خاصة على رقم الغرفة بشكل متكرر. لذا فإن الرقم الأول في التركيبة ينتج عن تطبيق الدالة على رقم الغرفة، والثاني ينتج عن تطبيق الدالة على الرقم الأول، والثالث عن تطبيق الدالة على الرقم الثاني.
ومع ذلك، تغيّر UMBRA بانتظام الدالة المستخدمة لتوليد التركيبات، لذا ستحتاج أداتك إلى أخذ رقم الغرفة والدالة المناسبة معًا لتوليد التركيبة.
نفّذ الدالة generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) لتوليد التركيبة التي ستحتاج إليها.
func makeCombo(_ x: Int) -> Int {
(x * 13) % 256
}
generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
سجّل في Exercism لتتعلّم وتتقن Swift عبر 35 مفهومًا116 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.