إعلان بنية shape
البنية shape نوع سجلّ بحقول مُسمّاة ومعلَّمة:
shape Point {
x: i32,
y: i32,
}
القطع:
shapeتُقدّم الإعلان.Pointاسم النوع.- الأقواس تُحيط بقائمة حقول، كلٌّ بصيغة
name: Type.
هذا الإعلان يُضيف نوعًا جديدًا اسمه Point إلى النطاق الحالي. في أيّ مكان تستطيع فيه استخدام نوع مضمَّن مثل i32، تستطيع الآن استخدام Point.
بناء قيمة من بنية
أنشئ حالة بتعبير قيمة حرفية للبنية:
let point = Point { x: 40, y: 2 }
تُسمّي القيمة الحرفية البنية وتُعيّن كل حقل. كل حقل يجب أن يكون حاضرًا — لا تُعيّن Zero بصمت قيمًا افتراضية صفر أو null للحقول المفقودة. إن نسيت واحدًا، يُخبرك المترجم:
{
"code": "FLD002",
"message": "missing field: y",
"line": 4
}
(رمز الخطأ الدقيق قد يختلف؛ الثابت هو مبدأ "لا قيم افتراضية ضمنية".)
تستطيع قراءة أو تعليق النوع صراحة إن أردت إبرازه:
let point: Point = Point { x: 40, y: 2 }
قراءة الحقول
الوصول إلى الحقول يستخدم صيغة النقطة:
let point = Point { x: 40, y: 2 }
let xVal = point.x
let yVal = point.y
point.x تقرأ حقل x. لا توجد دالة get_x() — الحقول بيانات بحتة.
مثال متكامل
هذا هو مثال point.0 التقليدي من مستودع اللغة — اضغط Run لتجربته:
اقرأه من الأعلى:
- أعلن بنية
Pointبحقلَين من النوعi32. - عرّف دالة
sumتأخذPointوتُعيد مجموع حقولها. - في
main، ابنِPoint، استدعِsum، وقارن النتيجة.
ثلاث خطوات، ثلاث أفكار متعلّقة بالبنى (إعلان، بناء، وصول)، وتأثير واحد — check world.out.write(...) في النهاية. لاحظ أن sum لا تمسّ World. هي دالة نقية على البيانات، والتوقيع يجعل ذلك واضحًا.
بِنى ذات حقول متداخلة
البنية تستطيع الاحتفاظ بقيم من أي نوع، بما في ذلك بِنى أخرى:
shape Range {
start: i32,
end: i32,
}
shape Segment {
label: String,
range: Range,
}
let seg = Segment {
label: "warmup",
range: Range { start: 0, end: 10 },
}
الوصول إلى الحقول يتسلسل كما تتوقّع:
let len = seg.range.end - seg.range.start
بِنى عامة (Generic)
عندما يجب أن تكون حقول البنية متعدّدة الأنواع، أعلن معاملات النوع بين قوسَين زاويين:
shape Pair<T, U> {
left: T,
right: U,
}
الحالات تُثبِّت المعاملات إلى أنواع ملموسة:
let intBytePair: Pair<i32, u8> = Pair { left: 40, right: 2_u8 }
let words: Pair<String, String> = Pair { left: "hello", right: "world" }
اسم نوع مستعار (type alias) يستطيع اختصار تعميم شائع:
type BytePair = Pair<u8, u8>
let bytes: BytePair = Pair { left: 1_u8, right: 2_u8 }
Generics يُغطّي معاملات النوع بعمق أكبر — بما في ذلك على الدوال، لا البِنى فقط.
ما لا تكونه البنى shapes
بعض الأشياء التي قد تتوقّعها من "struct" في لغة أخرى لا تتضمّنها البِنى عمدًا:
- لا دوال (methods). إعلان البنية بيانات فقط. السلوك يعيش في دوال حرّة تأخذ البنية كمعامل. هذا يعكس نفس الفصل بين البيانات والتأثيرات الذي تراه في الدوال.
- لا وراثة. البِنى لا تمتدّ من بِنى أخرى. إن أردت بنية مشتركة، استخرجها إلى حقل مشترك أو ابنِ نوع مجموع بـ choice.
- لا منشئات أو مُدمِّرات ضمنية. البناء هو تعبير القيمة الحرفية. التنظيف صريح — عندما تكشف المكتبة القياسية موارد تحتاج تنظيفًا، يتمّ ذلك عبر واجهات بنمط القدرات (capability-style APIs) بدلًا من RAII خفي.
- لا حقول خاصّة. كل حقول البنية متاحة للشيفرة التي تستطيع رؤية نوع البنية. الرؤية على مستوى النوع، لا على مستوى الحقل.
النمط: البِنى أنواع سجلّات بسيطة ومتوقّعة، وتبني كل شيء آخر منها.
متى تستخدم shape مقابل choice
دليل سريع:
- استخدم shape عندما تكون لقيمة كل هذه الحقول معًا.
Pointدائمًا لهxوy. - استخدم choice عندما تكون القيمة واحدة من عدة بدائل.
Resultإمّاokأوerr. - استخدم enum عندما لا تحمل البدائل بيانات إضافية — هي مجرّد تسميات. أيّام الأسبوع، حالات بسيطة.
هذه القطع الثلاث للبناء — shape (و)، وchoice (أو)، وenum (أو بدون حمولة) — تُغطّي تقريبًا كل احتياجات نمذجة البيانات.
التالي: التعميم Generics
رأيت Pair<T, U> يظهر عرضًا. التوثيق التالي، generics، يشرح كيف تعمل معاملات النوع على البِنى والدوال، بما في ذلك الأنماط التي تظهر في مكتبة Zero القياسية.
الأسئلة الشائعة
ما هي البنية shape في Zero؟
shape نوع منتج شبيه بـ struct في Zero — سجلّ مُسمّى بحقول معلَّمة. تُعلنها بـ shape Name { field1: T1, field2: T2 }، وتبني قيمًا منها بـ Name { field1: v1, field2: v2 }، وتقرأ الحقول بصيغة النقطة (value.field1). البِنى هي حجر البناء لنمذجة البيانات المنظَّمة.
كيف تُنشئ قيمة من بنية shape؟
استخدم تعبير قيمة حرفية للبنية يُسمّي الـ shape ويُعيّن كل حقل: let point = Point { x: 40, y: 2 }. كل حقل يجب ملؤه — لا تُعيّن Zero قيمًا افتراضية للحقول المفقودة بصمت. ترتيب الحقول في القيمة الحرفية ليس مضطرًا لمطابقة الإعلان.
كيف تختلف shape عن الصنف (class)؟
البنية shape بيانات بحتة — لها حقول، لكن لا دوال (methods) ولا وراثة ولا منشئات ضمنية. الدوال التي تعمل على بنية تأخذها كمعامل صراحة. هذا الفصل يُبقي اللغة صغيرة ويُبقي تكلفة بناء بنية أو نسخها متوقّعة، دون جداول دوال افتراضية خفية أو مُدمِّرات.
هل يمكن لبنى shape أن تكون عامة (generic) في Zero؟
نعم. أعلن معاملات النوع بين قوسَين زاويين: shape Pair<T, U> { left: T, right: U }. الحالات تُثبِّت تلك المعاملات إلى أنواع ملموسة: Pair<i32, u8>. البِنى العامة تظهر في كل أنحاء المكتبة القياسية — Maybe<T> وSpan<T> وغيرها كلها بِنى عامة أو أنواع مجموع مبنية على الفكرة نفسها.
هل تُنسخ البِنى أم تُمرَّر بالإشارة عند تمريرها للدوال؟
النموذج الذهني الافتراضي للبنى هو التمرير بالقيمة — الدالة المُستدعاة ترى نسختها المنطقية الخاصّة من البيانات، لا إشارة إلى ربط المستدعي. نموذج الذاكرة الدقيق في Zero قبل الإصدار 1.0 لا يزال يتطوّر (سترى ref وmutref في أمثلة المكتبة القياسية للأنواع المرجعية الصريحة). لمعظم شيفرة التطبيقات، عامل معاملات البنية كمدخلات بقيمة.