---
title: "متى تستعمل subscript آمنًا للمجموعات"
description: "الإضافة تحوّل انهيار الخروج عن الحدود إلى nil. وهذا مفيد حين يأتي الفهرس من خارج شيفرتك، ويخفي خطأً منطقيًّا حين لا يكون كذلك."
author: "Omar Albeik"
date: 2019-07-12
type: note
topics: [swift, api-design, software, engineering]
language: ar
reading_time_minutes: 2
canonical_url: https://omaralbeik.com/ar/blog/safe-collection-subscript
translation_url: https://omaralbeik.com/en/blog/safe-collection-subscript
source_url: https://omaralbeik.com/ar/blog/safe-collection-subscript.md
---

# متى تستعمل subscript آمنًا للمجموعات

الإضافة أربعة أسطر، وتكاد لا تخلو منها شيفرة Swift:

```swift
extension Collection {
  subscript(safe index: Index) -> Element? {
    indices.contains(index) ? self[index] : nil
  }
}
```

```swift
let names = ["John", "Mike"]

names[2]        // crash
names[safe: 2]  // nil
```

الخروج عن حدود المجموعة من الأشياء القليلة في Swift التي تُنهي العملية، وهذه
الإضافة تحوّله إلى `optional` يتعامل معه `if let`.

والمقايضة هي في موضع ظهور الخطأ. فـ‏`names[2]` في مصفوفةٍ من عنصرين تعني أنّ
شيفرةً سابقة أنتجت فهرسًا غير موجود. تتوقّف Swift عند ذلك الـ‏`subscript`
والفهرسُ الخاطئ في متناولك، و‏stack trace يبيّن كيف وصل إليه. ومع `[safe:]`
تحصل على `nil`، فلا يفعل الفرع شيئًا، ويصير العَرَض الظاهر صفًّا فارغًا أو
مجموعًا ناقصًا بواحد، في موضعٍ آخر ووقتٍ لاحق.

فالسؤال هو: هل تعرف أنّ الفهرس صحيح؟ إن كنت حسبته من `count`، أو كنت تمرّ على
`indices`، فأنت تعرف، ويضيف الـ‏`optional` فرعًا لحالةٍ لا تقع. وإن جاء الفهرس
من مكانٍ آخر فأنت لا تعرف:

- فهرس مأخوذ من حمولة بيانات أو من رابط
- اختيار حُفظ قبل إعادة التحميل واستُعمل بعدها
- فهرس أعاده callback من إطار عمل لمجموعة عدّلتها بعده

وفي الثلاث جميعًا تأتي المجموعة ويأتي الفهرس من مسارين مختلفين في الشيفرة،
وهذا هو ما ينبغي أن تبحث عنه.

وتفصيل في التنفيذ: `indices.contains(index)` فحص مدًى في `Array`، حيث `indices`
هي `Range<Int>` و‏`contains` بتعقيد O(1). أما في مجموعة لا تدعم الفهرسة
المباشرة فيتحوّل إلى `Sequence.contains`، الذي يمشي من فهرس البداية — فيكون
`someString[safe: i]` بتعقيد O(n) بطول النص، خلف شيء يبدو للقارئ `subscript`.
وحصر الإضافة في `RandomAccessCollection` يتجنّب ذلك، مقابل فقدانها على
`String`.

استعملها حيث يكون الفهرس غير موثوق. وفي غير ذلك، التوقّف أنفع من الـ‏`optional`.
