القوائم

في Scheme، القائمة بنية بيانات أساسية لتجميع القيم. القوائم مجموعات مرتبة من العناصر حيث يمكن أن يكون كل عنصر من أي نوع، بما في ذلك قائمة أخرى. تُستخدم القوائم على نطاق واسع في Scheme لتخزين البيانات وبنية البرنامج.

مثال 1: قائمة بسيطة

(list 1 2 3)
  • ينشئ قائمة من ثلاثة عناصر: 1، 2، و3.

النتيجة: (1 2 3)


الوصول إلى عناصر القائمة

يُصل إلى عناصر القائمة بإجراءات car وcdr:

  • car يسترد العنصر الأول.
  • cdr يسترد بقية القائمة (كل شيء ما عدا الأول).

أمثلة

(define my-list (list 1 2 3))
(car my-list)  ; يسترد العنصر الأول
(cdr my-list)  ; يسترد بقية القائمة

النتيجة:

  • (car my-list) تُرجع 1
  • (cdr my-list) تُرجع (2 3)

التكرار البسيط: المرور عبر القائمة

بالاستدعاء المتكرر لـ car على cdr القائمة، يمكن معالجة كل عنصر واحدًا تلو الآخر حتى اجتياز القائمة. هذا أساس كثير من خوارزميات معالجة القوائم.

مثال: طباعة كل عنصر في قائمة

(define (print-elements lst)
  (if (null? lst)
    (lumi-message "done")
    (begin
      (lumi-message (number->string (car lst))) ;; طباعة العنصر الأول
      (print-elements (cdr lst)))))             ;; معالجة بقية القائمة
  • الحالة الأساسية: إذا كانت القائمة فارغة (null? lst)، أوقف التكرار.
  • الحالة العودية: اطبع العنصر الأول (car lst)، ثم استدعِ الدالة على بقية القائمة (cdr lst).

مثال للاستخدام

(print-elements (list 1 2 3))

الإخراج:

  • "1"
  • "2"
  • "3"

النتيجة: "done"


كيف يعمل

  1. تسترد الدالة العنصر الأول بـ car وتعالجه.
  2. ثم تستدعي نفسها على بقية القائمة (cdr).
  3. تتكرر العملية حتى تصبح القائمة فارغة (null? lst).

مثال 2: أنواع مختلطة

يمكن أن تتضمن القوائم عناصر من أنواع مختلفة، بما في ذلك سلاسل أو قيم منطقية أو أرقام أو قوائم أخرى أو نتيجة تعبيرات:

(list 42 "hello" #t (list 1 2) (+ 3 4))
  • ينشئ قائمة تحتوي على:
    • رقم (42)
    • سلسلة ("hello")
    • قيمة منطقية (#t)
    • قائمة أخرى ((1 2))
    • نتيجة التعبير ((+ 3 4)، تُقيَّم إلى 7)

النتيجة: (42 "hello" #t (1 2) 7)


توضّح هذه الأمثلة تنوع القوائم في Scheme، ما يجعلها أداة قوية لتنظيم البيانات ومعالجتها.

بناء القوائم

يُستخدم cons لإنشاء قائمة جديدة بدمج عنصر مع قائمة موجودة.

(cons new-element existing-list)

مثال

(cons 0 (list 1 2 3))
  • يضيف 0 إلى بداية (1 2 3).

النتيجة: (0 1 2 3)


التحقق من القوائم

يتحقق list? مما إذا كانت القيمة المحددة قائمة.

(list? value)

مثال: list?

(list? (list 1 2 3))  ; يتحقق مما إذا كانت (list 1 2 3) قائمة
(list? 42)            ; يتحقق مما إذا كان 42 قائمة

النتيجة:

  • (list? (list 1 2 3)) تُرجع #t (صحيح)
  • (list? 42) تُرجع #f (خطأ)

العمليات على القوائم

يوفر Scheme عدة إجراءات مضمّنة للعمل مع القوائم، بما في ذلك:

  • length: إرجاع عدد العناصر.
  • append: دمج قائمتين أو أكثر في قائمة واحدة.
  • reverse: إرجاع قائمة جديدة بترتيب عكسي.
(length (list 1 2 3))          ; يرجع 3
(append (list 1 2) (list 3 4)) ; يرجع (1 2 3 4)
(reverse (list 1 2 3))         ; يرجع (3 2 1)

النتيجة:

  • (length (list 1 2 3)) تُرجع 3
  • (append (list 1 2) (list 3 4)) تُرجع (1 2 3 4)
  • (reverse (list 1 2 3)) تُرجع (3 2 1)

استخدام list-ref

يسترد list-ref العنصر عند فهرس محدد (فهرس يبدأ من الصفر).

(list-ref lst index)
  • lst: القائمة التي يُسترد منها العنصر.
  • index: فهرس يبدأ من الصفر للعنصر المطلوب.
مثال: list-ref
(list-ref (list 10 20 30 40) 2)  ; يسترد العنصر عند الفهرس 2

النتيجة: 30


القوائم المتداخلة

يمكن أن تحتوي القوائم في Scheme على قوائم أخرى كعناصر، ما يُنشئ بنية متداخلة.

مثال: إنشاء قائمة متداخلة

(define nested-list (list (list 1 2) (list 3 4) (list 5)))
  • ينشئ قائمة من ثلاثة عناصر، كل منها قائمة.

النتيجة: ((1 2) (3 4) (5))


الوصول إلى البيانات المتداخلة

للوصول إلى عناصر داخل قائمة متداخلة، استخدم مجموعات من car وcdr للتنقل في البنية.

مثال: الوصول إلى العناصر

(car nested-list)              ; يسترد العنصر الأول: (1 2)
(car (car nested-list))        ; يسترد العنصر الأول من القائمة الفرعية الأولى: 1
(cdr (car nested-list))        ; يسترد بقية القائمة الفرعية الأولى: (2)
(car (cdr (car nested-list)))  ; يسترد العنصر الثاني من القائمة الفرعية الأولى: 2

شرح

  1. car nested-list:

    • يسترد العنصر الأول من nested-list، وهو (1 2).
  2. car (car nested-list):

    • يسترد العنصر الأول من (1 2)، وهو 1.
  3. cdr (car nested-list):

    • يسترد بقية (1 2)، وهو (2).
  4. car (cdr (car nested-list)):

    • يسترد العنصر الأول من (2)، وهو 2.

مثال: الوصول إلى عناصر من قوائم فرعية أخرى

(car (cdr nested-list))        ; يسترد القائمة الفرعية الثانية: (3 4)
(car (car (cdr nested-list)))  ; يسترد العنصر الأول من القائمة الفرعية الثانية: 3

يسمح هذا الأسلوب بالتنقل منهجيًا والوصول إلى عناصر محددة في قائمة متداخلة، ما يوفر مرونة قوية للبيانات الهرمية.

ملخص

  • القوائم في Scheme هياكل بيانات أساسية ومتعددة الاستخدامات.
  • استخدم list للإنشاء، وcar/cdr للوصول، وcons للبناء.
  • إجراءات مثل length وappend وreverse وlist-ref تسهّل عمليات القوائم.
  • يمكن أن تكون القوائم متداخلة، ما يتيح هياكل بيانات معقدة.