اگر همهی اسمها و برچسبها را از امضای یک تابع 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)