{"id":"l-sw-1-4","courseId":"swift-essentials","lang":"ar","kind":"lesson","summary":"اكتب دوال بتسميات وسائط واضحة وقيم افتراضية، ثم استبدل حلقات التكرار المكتوبة يدويًا بـ closures تمرّرها إلى filter وmap وreduce وsorted.","html":"<p>حلقات <code dir=\"ltr\">for</code> من الدرس السابق تعمل، لكنها تجعلك تقرأ خمسة أسطر لتعرف معلومة واحدة، مثل «مجموع ما أُنفق على الطعام». الدوال تعطي قطعة من المنطق اسمًا. والـ closures تتيح لك أن تسلّم قطعة صغيرة من المنطق إلى طرف آخر، مثل «أبقِ ما يزيد على 50»، ودوال المجموعات في Swift مبنية حولها. معًا تحوّلان معظم حلقات التكرار في Pocket Budget إلى سطر واحد مقروء.</p>\n<p>للأمثلة، إليك نوع مصروف بسيطًا. ستتعلّم ما يعنيه <code dir=\"ltr\">struct</code> فعلًا في القسم التالي؛ أما الآن فاقرأه على أنه «قيمة لها عنوان ومبلغ وتصنيف».</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Expense.swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Foundation</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">struct</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> title: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount: Decimal</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> category: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Groceries\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">64.2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Bus pass\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">45</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Transport\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4.5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Concert\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">80</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Fun\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span></code></pre></div>\n<h2 id=\"sec-1\" tabindex=\"-1\">دوال تُقرأ كالجمل</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> total</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">of</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses: [Expense], </span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> category: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> nil</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Decimal {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sum: Decimal </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">where</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> nil</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ||</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense.category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> category {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        sum </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense.amount</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sum</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">total</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">of</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: expenses)                  </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// 193.7</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">total</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">of</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: expenses, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)      </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// 68.7</span></span></code></pre></div>\n<p>لكل معامل اسمان. <strong>تسمية الوسيط</strong> (argument label) مثل <code dir=\"ltr\">of</code> و<code dir=\"ltr\">in</code> هي ما يكتبه من يستدعي الدالة؛ و<strong>اسم المعامل</strong> (parameter name) مثل <code dir=\"ltr\">expenses</code> و<code dir=\"ltr\">category</code> هو ما يستخدمه جسم الدالة. هذا الفصل هو سبب قراءة مواضع الاستدعاء في Swift كأنها جمل إنجليزية: “total of expenses in Food”. والجزء <code dir=\"ltr\">= nil</code> يعطي <code dir=\"ltr\">category</code> قيمة افتراضية، فيستطيع المستدعي حذفه. اكتب <code dir=\"ltr\">_</code> كتسمية حين لا تضيف شيئًا، كما في <code dir=\"ltr\">print(_:)</code>.</p>\n<p>يعلن <code dir=\"ltr\">-&gt; Decimal</code> نوع القيمة المُعادة. والدالة التي لا تعيد شيئًا تحذف السهم.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ closures: دوال بلا أسماء</h2>\n<p>الـ closure (دالة مجهولة الاسم) كتلة كود يمكنك تخزينها في ثابت أو تمريرها كوسيط. إليك closure يقرّر ما إذا كان المصروف كبيرًا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> isLarge: (Expense) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Bool</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { expense </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">isLarge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expenses[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])     </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// true</span></span></code></pre></div>\n<p>يُقرأ النوع <code dir=\"ltr\">(Expense) -&gt; Bool</code> «يأخذ <code dir=\"ltr\">Expense</code> ويعيد <code dir=\"ltr\">Bool</code>». المعاملات تأتي قبل <code dir=\"ltr\">in</code>، والجسم بعدها. والجسم المكوّن من تعبير واحد يعيد قيمته دون كتابة <code dir=\"ltr\">return</code>.</p>\n<p>الآن مرّر منطقًا كهذا إلى <code dir=\"ltr\">filter</code>. هذه الأسطر الثلاثة هي الاستدعاء نفسه، مختصرًا شيئًا فشيئًا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> large1 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: Expense) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Bool</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> in</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">})</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> large2 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { expense </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> large3 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span></code></pre></div>\n<p>حين يكون الـ closure آخر وسيط، يمكنك كتابته بعد الأقواس (<strong>صيغة الـ trailing closure</strong>) وحذف الأقواس الفارغة كليًا. وSwift تعرف الأنواع مسبقًا من توقيع <code dir=\"ltr\">filter</code>، فيمكنك حذفها أيضًا. <code dir=\"ltr\">$0</code> هو المعامل الأول، و<code dir=\"ltr\">$1</code> الثاني.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>متى تتوقّف عن الاختصار</span></p>\n<p>استخدم <code dir=\"ltr\">$0</code> في الـ closures المكوّنة من سطر واحد حين يكون المعنى واضحًا. وحين يمتدّ الـ closure على عدة أسطر أو يأخذ معاملين تحتاج إلى التمييز بينهما، فسمِّ المعاملات. أنت نفسك في المستقبل القارئ الأول لهذا الكود.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">filter وmap وreduce وsorted</h2>\n<p>هذه الأربع تغطّي معظم ما تفعله مع المجموعات:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> food </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }        </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// keep matching expenses</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> titles </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> food.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.title }                           </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// [\"Groceries\", \"Coffee\"]</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> foodTotal </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> food.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">reduce</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount }            </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// 68.7</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> biggestFirst </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">sorted</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount } </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// Concert, Groceries, ...</span></span></code></pre></div>\n<p>يبدأ <code dir=\"ltr\">reduce</code> من قيمة ابتدائية (0) ويطوي كل عنصر في نتيجة متراكمة: <code dir=\"ltr\">$0</code> هو المجموع حتى الآن و<code dir=\"ltr\">$1</code> هو المصروف التالي. ويسأل <code dir=\"ltr\">sorted(by:)</code> الـ closure الخاص بك: «هل يأتي <code dir=\"ltr\">$0</code> قبل <code dir=\"ltr\">$1</code>؟».</p>\n<p>اربطها في سلسلة، فيُقرأ خطّ المعالجة بالترتيب الذي يُنفَّذ به:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> foodSpend </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(\\.amount)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">reduce</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span></code></pre></div>\n<p><code dir=\"ltr\">\\.amount</code> هو <strong>key path</strong> (مسار مفتاح)، اختصار لـ <code dir=\"ltr\">{ $0.amount }</code>، و<code dir=\"ltr\">+</code> هو نفسه دالة تأخذ قيمتين وتعيد مجموعهما، فيمكنك تمريره مباشرة إلى <code dir=\"ltr\">reduce</code>.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 170\" role=\"img\" aria-labelledby=\"l-sw-1-4-t1\"><defs><marker id=\"arrow-l-sw-1-4-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-sw-1-4-t1\">أربعة مصاريف تدخل إلى filter الذي يُبقي مصروفي الطعام؛ ثم يحوّلهما map إلى مبلغين؛ ثم يجمعهما reduce في مجموع واحد هو 68.7.</title>\n  <rect class=\"d-box\" x=\"10\" y=\"50\" width=\"130\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"75\" y=\"80\" text-anchor=\"middle\">4 مصاريف</text>\n  <text class=\"d-label-muted\" x=\"75\" y=\"102\" text-anchor=\"middle\">[Expense]</text>\n  <path class=\"d-arrow\" d=\"M140 85 L185 85\" marker-end=\"url(#arrow-l-sw-1-4-1)\"/>\n  <rect class=\"d-box-primary\" x=\"190\" y=\"50\" width=\"140\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"260\" y=\"80\" text-anchor=\"middle\">filter</text>\n  <text class=\"d-label-muted\" x=\"260\" y=\"102\" text-anchor=\"middle\">عنصرا طعام</text>\n  <path class=\"d-arrow\" d=\"M330 85 L375 85\" marker-end=\"url(#arrow-l-sw-1-4-1)\"/>\n  <rect class=\"d-box-accent\" x=\"380\" y=\"50\" width=\"140\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"450\" y=\"80\" text-anchor=\"middle\">map(\\.amount)</text>\n  <text class=\"d-label-muted\" x=\"450\" y=\"102\" text-anchor=\"middle\">[64.2, 4.5]</text>\n  <path class=\"d-arrow\" d=\"M520 85 L565 85\" marker-end=\"url(#arrow-l-sw-1-4-1)\"/>\n  <rect class=\"d-box-success\" x=\"570\" y=\"50\" width=\"120\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"630\" y=\"80\" text-anchor=\"middle\">reduce</text>\n  <text class=\"d-label-muted\" x=\"630\" y=\"102\" text-anchor=\"middle\">68.7</text>\n  <text class=\"d-label-muted\" x=\"350\" y=\"155\" text-anchor=\"middle\">كل خطوة تعيد قيمة جديدة؛ والمصفوفة الأصلية لا تتغيّر أبدًا</text>\n</svg><figcaption>filter وmap وreduce كخطّ معالجة</figcaption></figure>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>استدعاء sorted وتجاهل النتيجة</span></p>\n<p><code dir=\"ltr\">expenses.sorted { … }</code> في سطر مستقل لا يفعل شيئًا مفيدًا: يعيد مصفوفة جديدة ثم يرميها، ويحذّرك Xcode بالرسالة “result of call to ‘sorted(by:)’ is unused”. أسند النتيجة، أو استدعِ <code dir=\"ltr\">sort(by:)</code> على مصفوفة <code dir=\"ltr\">var</code> لترتيبها في مكانها.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">الـ closures تلتقط ما حولها</h2>\n<p>يستطيع الـ closure أن يستخدم متغيّرات من النطاق الذي أُنشئ فيه، ويُبقيها حيّة:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"6\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> makeLimitCheck</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">limit</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: Decimal) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (Decimal) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Bool</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> limit }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> overFoodLimit </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> makeLimitCheck</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">limit</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">60</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">overFoodLimit</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">64.2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)     </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// true</span></span></code></pre></div>\n<p>انتهت <code dir=\"ltr\">makeLimitCheck</code>، ومع ذلك ما زال الـ closure يعرف أن <code dir=\"ltr\">limit</code> يساوي 60. وحين تخزّن دالة معامل closure لتستدعيه لاحقًا، بدل أن تستدعيه قبل أن تعود، تُلزمك Swift بتعليم هذا المعامل بـ <code dir=\"ltr\">@escaping</code>. هذه الكلمة ملصق تحذيري للقرّاء: هذا الـ closure يعيش أطول من الاستدعاء، فكل ما يلتقطه يبقى حيًّا أيضًا.</p>\n<p>هذا <strong>الالتقاط</strong> (capturing) هو ما يسمح لأزرار SwiftUI بتشغيل كود يشير إلى بيانات الـ view بعد بنائه بوقت طويل. وله حدّ حادّ واحد، هو دورة المراجع (reference cycle) حين يلتقط class وclosure كلٌّ منهما الآخر، وستقابله مع الـ classes في الدرس التالي.</p>\n<p>صار بإمكانك الآن أن تسمّي المنطق، وتمرّره، وتستبدل حلقات التكرار بخطوط معالجة. بهذا تكتمل أساسيات اللغة. القسم التالي عن تصميم البيانات: أن تقرّر هل تكون بيانات Pocket Budget من نوع struct أو class أو enum، ولماذا يغيّر هذا الاختيار سلوك تطبيقك.</p>\n","toc":[{"id":"sec-1","text":"دوال تُقرأ كالجمل","level":2},{"id":"sec-2","text":"الـ closures: دوال بلا أسماء","level":2},{"id":"sec-3","text":"filter وmap وreduce وsorted","level":2},{"id":"sec-4","text":"الـ closures تلتقط ما حولها","level":2}],"takeaways":["تسميات الوسائط تجعل مواضع الاستدعاء تُقرأ كجمل؛ استخدم <code dir=\"ltr\">_</code> فقط حين لا تضيف التسمية شيئًا.","الـ closure دالة بلا اسم، وصيغة الـ trailing closure تتيح لك كتابته بعد أقواس الاستدعاء.","<code dir=\"ltr\">filter</code> يُبقي العناصر، و<code dir=\"ltr\">map</code> يحوّلها، و<code dir=\"ltr\">reduce</code> يجمعها في قيمة واحدة، و<code dir=\"ltr\">sorted(by:)</code> يعيد مصفوفة جديدة مرتّبة.","الـ closure يلتقط المتغيّرات التي يستخدمها، فيستطيع أن يحمل سياقًا مثل حدّ معيّن إلى أي مكان يُستدعى فيه لاحقًا."],"further":[{"title":"Functions","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/"},{"title":"Closures","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/"}],"quiz":[{"q":"<p>لديك <code dir=\"ltr\">func total(of expenses: [Expense], in category: String? = nil) -&gt; Decimal</code>. أيّ استدعاء يُترجَم؟</p>","options":[{"text":"<code dir=\"ltr\">total(expenses, &quot;Food&quot;)</code>","why":"لكلا المعاملين تسمية وسيط، فيجب أن يستخدمها الاستدعاء."},{"text":"<code dir=\"ltr\">total(expenses: expenses)</code>","why":"<code dir=\"ltr\">expenses</code> هو اسم المعامل المستخدم داخل الدالة. أما من يستدعيها فيستخدم التسمية <code dir=\"ltr\">of</code>."},{"text":"<code dir=\"ltr\">total(of: expenses)</code>","why":"صحيح. للمعامل الثاني قيمة افتراضية، فيمكنك حذفه."}],"answer":2},{"q":"<p>ماذا ينتج <code dir=\"ltr\">[3, 8, 12].map { $0 * 2 }.filter { $0 &gt; 10 }</code>؟</p>","options":[{"text":"<code dir=\"ltr\">[16, 24]</code>","why":"صحيح. يضاعف <code dir=\"ltr\">map</code> كل رقم فينتج <code dir=\"ltr\">[6, 16, 24]</code>، ثم يُبقي <code dir=\"ltr\">filter</code> ما هو أكبر من 10."},{"text":"<code dir=\"ltr\">[24]</code>","why":"هذا ما يحدث لو طبّقت الفلترة قبل التحويل (<code dir=\"ltr\">12</code> هي القيمة الوحيدة الأكبر من 10). السلسلة تُنفَّذ من اليسار إلى اليمين."},{"text":"<code dir=\"ltr\">[6, 16, 24]</code>","why":"هذه النتيجة بعد <code dir=\"ltr\">map</code> فقط؛ وما زال على <code dir=\"ltr\">filter</code> أن يحذف 6."},{"text":"<code dir=\"ltr\">40</code>","why":"القيمة الواحدة المجمّعة هي ما ينتجه <code dir=\"ltr\">reduce</code>. أما <code dir=\"ltr\">map</code> و<code dir=\"ltr\">filter</code> فكلاهما يعيد مصفوفة."}],"answer":0},{"q":"<p>كتبت <code dir=\"ltr\">expenses.sorted { $0.amount &gt; $1.amount }</code> في سطر مستقل ولم يتغيّر شيء. لماذا؟</p>","options":[{"text":"الـ closure يقارن في الاتجاه المعاكس.","why":"المقارنة سليمة (الأكبر أولًا). المشكلة في النتيجة."},{"text":"<code dir=\"ltr\">sorted</code> يعيد مصفوفة جديدة، والكود يرمي هذه النتيجة.","why":"صحيح. أسندها (<code dir=\"ltr\">let biggestFirst = …</code>) أو استدعِ <code dir=\"ltr\">sort</code> على <code dir=\"ltr\">var</code> لترتيبها في مكانها. ويحذّرك Xcode من النتيجة غير المستخدمة."},{"text":"الـ closures لا تستطيع قراءة خصائص مثل <code dir=\"ltr\">amount</code>.","why":"الـ closures تستطيع قراءة أي شيء في نطاقها، بما في ذلك خصائص معاملاتها."}],"answer":1},{"q":"<p><code dir=\"ltr\">let check = makeLimitCheck(limit: 60)</code> تعيد الـ closure‏ <code dir=\"ltr\">{ amount in amount &gt; limit }</code>. ماذا يعيد <code dir=\"ltr\">check(64)</code> بعد انتهاء <code dir=\"ltr\">makeLimitCheck</code> بوقت طويل؟</p>","options":[{"text":"لا يُترجَم، لأن <code dir=\"ltr\">limit</code> لم يعد موجودًا.","why":"الـ closure التقط <code dir=\"ltr\">limit</code>، فيبقى حيًّا ما بقي الـ closure."},{"text":"<code dir=\"ltr\">false</code>، لأن القيم الملتقَطة تعود إلى الصفر.","why":"القيم الملتقَطة تحتفظ بقيمها؛ لا شيء يعود إلى الصفر."},{"text":"<code dir=\"ltr\">true</code>","why":"صحيح. الـ closure التقط <code dir=\"ltr\">limit</code> بقيمة 60، و64 أكبر من 60."}],"answer":2}],"exercise":{"kind":"fill","language":"swift","template":"// expenses: [Expense], each with title, amount and category\nlet large = expenses.{{0}} { $0.amount > 50 }\nlet titles = large.{{1}} { $0.title }\nlet spent = expenses.{{2}}(0) { $0 + $1.amount }\nlet biggestFirst = expenses.sorted { $0.amount {{3}} $1.amount }","blanks":[{"answers":["filter"]},{"answers":["map"]},{"answers":["reduce"]},{"answers":[">"]}],"title":"استبدل حلقات التكرار بـ closures","prompt":"<p>تحتاج شاشة الملخّص في Pocket Budget إلى أربع قيم. املأ كل فراغ بحيث يحمل <code dir=\"ltr\">large</code> المصاريف التي تزيد على 50، ويحمل <code dir=\"ltr\">titles</code> عناوينها، ويكون <code dir=\"ltr\">spent</code> مجموع كل المبالغ، ويعرض <code dir=\"ltr\">biggestFirst</code> كل المصاريف من أكبر مبلغ إلى أصغره.</p>\n","hints":["كل فراغ من الفراغات الثلاثة الأولى هو اسم دالة من دوال المجموعات في هذا الدرس.","يأخذ <code dir=\"ltr\">reduce</code> قيمة ابتدائية وclosure يجمع المجموع المتراكم (<code dir=\"ltr\">$0</code>) مع العنصر التالي (<code dir=\"ltr\">$1</code>).","يسأل <code dir=\"ltr\">sorted(by:)</code>: «هل يأتي <code dir=\"ltr\">$0</code> قبل <code dir=\"ltr\">$1</code>؟». لترتيب الأكبر أولًا، يكون الجواب نعم حين يكون <code dir=\"ltr\">$0</code> أكبر."],"explanation":"<p>يُبقي <code dir=\"ltr\">filter</code> العناصر التي يعيد لها الـ closure القيمة <code dir=\"ltr\">true</code>، ويحوّل <code dir=\"ltr\">map</code> كل مصروف إلى عنوانه، ويطوي <code dir=\"ltr\">reduce(0)</code> كل المبالغ في مجموع واحد. أما <code dir=\"ltr\">sorted</code> فيضع <code dir=\"ltr\">$0</code> أولًا كلما أعاد الـ closure القيمة <code dir=\"ltr\">true</code>، لذلك يعطي <code dir=\"ltr\">$0.amount &gt; $1.amount</code> ترتيبًا تنازليًا؛ ولو استخدمت <code dir=\"ltr\">&lt;</code> لجاء الأرخص أولًا.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> large </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> titles </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> large.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.title }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> spent </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">reduce</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> biggestFirst </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">sorted</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.amount }</span></span></code></pre></div>\n","checkLabels":{}},"words":598,"readMinutes":4}