إرجاع Closures
جزء من قسم المنطق والتدفق في رحلة Swift على Coddy — الدرس 41 من 56.
لقد رأيت makeCounter تُرجع إغلاقاً (closure). تتيح لك نفس الحيلة بناء سلوك قابل للتكوين: خذ المعاملات مرة واحدة، واحصل على دالة تستخدمها عدة مرات.
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
let tenfold = multiplier(10)
print(triple(4)) // 12
print(tenfold(4)) // 40يلتقط الإغلاق (closure) المُرجع k، لذا فإن كل استدعاء لـ multiplier(...) ينتج إغلاقاً جديداً تماماً بـ k الخاصة به.
هذا النمط هو جوهر كود "الاستراتيجية" (strategy) في Swift: اكتب دالة تأخذ إعدادات (configuration) وتُرجع إغلاقاً (closure)، ثم مرر هذا الإغلاق إلى map أو filter أو sorted(by:) أو أي مكان آخر يُتوقع فيه قيمة على شكل دالة.
التحدي
متوسطقم ببناء مصنعين للإغلاقات (closure factories):
greaterThan(_ k: Int) -> (Int) -> Bool: تعيد دالة منطقية (predicate) تكونtrueعندما يكون المعامل الخاص بها أكبر تماماً منkscaleBy(_ k: Int) -> (Int) -> Int: تعيد دالة تضرب المعامل الخاص بها فيk
اقرأ ثلاثة أسطر:
- عدد صحيح
threshold - عدد صحيح
scale - قائمة من الأعداد الصحيحة مفصولة بفاصلة، وهي
nums
اطبع ثلاثة أسطر:
- الأرقام التي تتجاوز العتبة (قم بالتصفية باستخدام الإغلاق من
greaterThan)، مدمجة بـ, - نفس الأرقام، بعد تغيير حجمها (استخدم الخريطة map مع
scaleBy)، مدمجة بـ, - عدد الأرقام التي اجتازت التصفية
للمدخلات 5 / 3 / 2,7,3,8,9، تكون المخرجات:
7,8,9
21,24,27
3ورقة مرجعية
إنّ مصنع الإغلاقات (closure factory) هو دالة تلتقط معاملاً وتُرجع إغلاقاً جديداً مهيأً بواسطته:
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
print(triple(4)) // 12تنتج كل عملية استدعاء إغلاقاً جديداً تماماً بقيمته الملتقطة الخاصة لـ k. يمكن تمرير الإغلاقات المرجعة مباشرة إلى map، و filter، و sorted(by:)، وما إلى ذلك:
func greaterThan(_ k: Int) -> (Int) -> Bool {
return { n in n > k }
}
let nums = [2, 7, 3, 8, 9]
let filtered = nums.filter(greaterThan(5)) // [7, 8, 9]
let scaled = filtered.map(multiplier(3)) // [21, 24, 27]جرّب بنفسك
let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// TODO: greaterThan، scaleBy؛ التصفية (filter) ثم التعيين (map)؛ طباعة العناصر مدمجة والعدد
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس المنطق والتدفق
1النصوص بعمق
العد والفهارسحالة الأحرف وإزالة الفراغاتالبحث في النصوصتقسيم ودمج النصوصاستبدال النصوص الفرعيةمراجعة - التحقق من اسم المستخدم4المجموعات
إنشاء المجموعاتالاتحاد والتقاطعالطرح والفرق المتماثلالمجموعات الجزئية والشاملةمراجعة - تصفية الـ Tag7مشروع - متتبع العادات
نظرة عامة على المشروعتحديد كمكتمل2النطاقات والخطوات
المغلقة مقابل نصف المفتوحةالخطوة (Stride)دوال النطاقاتالنطاقات في Switchملخص - شبكة التقويم5الدوال من الرتبة العليا - الجزء الأول
MapFilterReduceربط Map و Filter و Reduceمراجعة - إحصائيات الكلمات8Closures
أساسيات ClosuresTrailing Closuresالتقاط القيمإرجاع Closuresدوال Higher-Order مخصصةمراجعة - بناء Pipeline