البرمجة الوظيفية في Swift: من الإغلاقات إلى التركيب
تم تصميم Swift في الأصل كلغة متعددة النماذج. وهو يدعم البرمجة الكائنية والبرمجة القائمة على البروتوكول والبرمجة الوظيفية. يساعد النهج الوظيفي في كتابة كود أكثر قابلية للتنبؤ والاختبار والأمان في التزامن. في هذه المقالة، سنشرح المفاهيم الأساسية للبرمجة الوظيفية في Swift مع أمثلة عملية.
1. الدوال النقية (Pure Functions) وعدم القابلية للتغيير (Immutability)
أساس الأسلوب الوظيفي هو الدوال النقية. هذه الدالة تُرجع دائمًا نفس النتيجة لنفس الوسائط وليس لها آثار جانبية (لا تغير الحالة الخارجية).
// دالة غير نقية — تغير متغيرًا خارجيًاvar total = 0func addToTotal(_ value: Int) -> Int { total += value return total}
// دالة نقية — مجرد حسابfunc add(_ a: Int, _ b: Int) -> Int { return a + b}يتم تحقيق عدم القابلية للتغيير (Immutability) من خلال let والهياكل (structs) ذات دلالات القيمة. بدلاً من تعديل المصفوفة، نقوم بإنشاء مصفوفة جديدة:
let numbers = [1, 2, 3, 4, 5]// بدلاً من var و append:let newNumbers = numbers + [6] // [1, 2, 3, 4, 5, 6]2. الإغلاقات (Closures) كلبنات بناء
الإغلاقات في Swift هي دوال مجهولة يمكنها التقاط المتغيرات من السياق المحيط. وهي "مواطنون من الدرجة الأولى": يمكن تمريرها كمعاملات وإرجاعها من الدوال.
// إغلاق بسيطlet multiply: (Int, Int) -> Int = { $0 * $1 }let result = multiply(3, 4) // 12
// إغلاق مع التقاط السياقvar counter = 0let increment = { counter += 1 }increment() // counter = 1increment() // counter = 2تُستخدم الإغلاقات بنشاط في دوال الترتيب الأعلى (Higher-Order Functions)، مثل sorted:
let names = ["Иван", "Анна", "Борис", "Елена"]let sorted = names.sorted { $0.localizedStandardCompare($1) == .orderedAscending }print(sorted) // ["Анна", "Борис", "Елена", "Иван"]3. دوال الترتيب الأعلى: map, filter, reduce
هذه هي "أداة العمل" للأسلوب الوظيفي في Swift. إنها تسمح بمعالجة المجموعات بدون حلقات صريحة أو تحوير (mutation).
map
تحول كل عنصر من عناصر المجموعة:
let prices = [100, 200, 300]let withTax = prices.map { $0 * 1.2 }print(withTax) // [120.0, 240.0, 360.0]
// مثال واقعي: استخراج الأسماء من مصفوفة النماذجstruct User { let name: String let age: Int}let users = [User(name: "Алексей", age: 30), User(name: "Мария", age: 25)]let userNames = users.map { $0.name }print(userNames) // ["Алексей", "Мария"]filter
يختار العناصر وفقًا لشرط:
let numbers = [1, 2, 3, 4, 5, 6]let evenNumbers = numbers.filter { $0 % 2 == 0 }print(evenNumbers) // [2, 4, 6]
// تصفية المستخدمين الأكبر من 18 عامًاlet adults = users.filter { $0.age >= 18 }reduce
يختزل المجموعة إلى قيمة واحدة:
let sum = numbers.reduce(0, +) // 21// تجميع سلسلة من مصفوفةlet words = ["Функциональное", "программирование", "Swift"]let sentence = words.reduce("") { $0.isEmpty ? $1 : $0 + " " + $1 }print(sentence) // "Функциональное программирование Swift"دمج الدوال
الأكثر إثارة للاهتمام هو سلاسل الاستدعاءات:
let transactions = [250, -50, 100, -200, 300, -100]let balance = transactions .filter { $0 > 0 } // الإيرادات فقط .map { $0 * 0.87 } // خصم ضريبة 13% .reduce(0, +) // الجمعprint(balance) // 565.54. تركيب الدوال (Function Composition) والكاري (Currying)
التركيب يسمح بدمج عدة دوال في دالة واحدة. في Swift لا يوجد عامل تركيب مدمج