هل من الصحيح استخدام backtick / فاصلة لغة داخل (حلقة ...)?

StackOverflow https://stackoverflow.com/questions/101487

  •  01-07-2019
  •  | 
  •  

سؤال

لدي بعض التعليمات البرمجية التي تقوم بجمع النقاط (consed الأعداد الصحيحة) من حلقة التي تبدو شيئا مثل هذا:

(loop
    for x from 1   to     100
    for y from 100 downto 1
        collect `(,x . ,y))

سؤالي هو: هل من الصحيح استخدام `(,x . ,y) في هذه الحالة ؟

تحرير:هذه العينة لا حول توليد جدول 100x100 البنود, رمز هنا فقط توضيح استخدام اثنين من حلقة المتغيرات consing من قيمها.لقد تحريرها حلقة لجعل هذا واضح.الفعلية حلقة يمكنني استخدام يعتمد على عدة وظائف أخرى (و هو جزء من واحد نفسه) لذلك كان من المنطقي أن تحل محل المكالمات مع حرفية الصحيحه وسحب حلقة من وظيفة.

هل كانت مفيدة؟

المحلول

سيكون ذلك أفضل أن تفعل فقط (سلبيات x y).

ولكن الإجابة على السؤال, هناك حرج في أن :) (ما عدا مما يجعل صبي أبطأ).

نصائح أخرى

أعتقد أن الإجابة هنا هي استخدام الموارد (التالية من هذا المنصب)

على سبيل المثال في clisp:

[1]> (time
         (progn
             (loop
                 for x from 1 to 100000
                 for y from 1 to 100000 do
                     collect (cons x y))
         ()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
         CL.
Real time: 0.469 sec.
Run time: 0.468 sec.
Space: 1609084 Bytes
GC: 1, GC time: 0.015 sec.
NIL
[2]> (time
         (progn
             (loop
                 for x from 1 to 100000
                 for y from 1 to 100000 do
                     collect `(,x . ,y)) ;`
         ()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
         CL.
Real time: 0.969 sec.
Run time: 0.969 sec.
Space: 10409084 Bytes
GC: 15, GC time: 0.172 sec.
NIL
[3]>

dsm:هناك بضعة أشياء غريبة عن الكود الخاص بك هنا.علما بأن

(loop for x from 1 to 100000
  for y from 1 to 100000 do
  collect `(,x . ,y))

يعادل:

(loop for x from 1 to 100
   collecting (cons x x))

والتي ربما ليس تماما ما كنت المقصود.ملاحظة ثلاثة أمور:أولا الطريقة التي كنت قد كتبت ذلك ، x و y لها نفس الدور.ربما من المفترض أن عش الحلقات.ثانيا ، هل بعد y غير صحيحة ، كما أن هناك لا يسب شكل بعد ذلك.ثالثا: أنت على حق أنه يمكن استخدام backtick النهج هنا ولكن يجعل التعليمات البرمجية الخاصة بك من الصعب قراءة و لا الاصطلاحية على أي مكسب ، لذلك من الأفضل تجنبها.

التخمين في ما كنت تهدف في الواقع ، قد تفعل شيئا من هذا القبيل (باستخدام حلقة):

(loop for x from 1 to 100 appending 
  (loop for y from 1 to 100 collecting (cons x y)))

إذا كنت لا ترغب في حلقة الكلي (مثل كايل), يمكنك استخدام التكرار آخر بناء مثل

(let ((list nil)) 
   (dotimes (n 100) ;; 0 based count, you will have to add 1 to get 1 .. 100
     (dotimes (m 100) 
       (push (cons n m) list)))
   (nreverse list))

إذا كنت تجد نفسك تفعل هذا النوع من الشيء الكثير, ربما يجب عليك كتابة المزيد من الوظيفة العامة من أجل عبور القوائم ، ثم تمر عليه هذه القوائم من الاعداد الصحيحه

إذا كان لديك مشكلة مع التكرار ، وليس مجرد حلقة, يمكنك أن تفعل هذا النوع من الشيء بشكل متكرر (لكن لاحظ هذه ليست خطة التنفيذ قد لا يضمن TCO).وظيفة "genint" أظهرت كايل هنا هو البديل مشترك (ولكن ليس معيار) وظيفة ذرة.ومع ذلك, إضافة إلى قائمة هو فكرة سيئة.أي ما يعادل تنفيذ مثل هذا:

(defun iota (n &optional (start 0))
  (let ((end (+ n start)))
    (labels ((next (n)
               (when (< n end) 
                 (cons n (next (1+ n))))))
      (next start))))

ينبغي أن يكون أكثر كفاءة بكثير, ولكن لا يزال لا ذيل استدعاء.ملاحظة لقد وضع هذا الأمر على أكثر من المعتاد 0 ولكن نظرا كنت معلمة اختيارية تبدأ في 1 أو أي عدد صحيح.بالطبع ما سبق يمكن كتابة شيء من هذا القبيل:

(defun iota (n &optional (start 0))
  (loop repeat n 
     for i from start collecting i))

والذي لديه ميزة من لا تهب كومة كبيرة من الحجج.إذا كان التطبيق الخاص بك يدعم ذيل استدعاء القضاء ، يمكنك أيضا تجنب العودية تشغيل الخروج من المكان قبل أن تفعل شيئا مثل هذا:

(defun iota (n &optional (start 0))
  (labels ((next (i list)
             (if (>= i (+ n start))
                 nil
                 (next (1+ i) (cons i list)))))
    (next start nil)))

على أمل أن يساعد!

لماذا لا مجرد

(cons x y)

بالمناسبة حاولت تشغيل التعليمات البرمجية الخاصة بك في CLISP و لم تعمل كما هو متوقع.وبما أنني لست مروحة كبيرة من حلقة الكلي هنا هو كيف يمكن تحقيق نفس الشيء بشكل متكرر:

(defun genint (stop)
  (if (= stop 1) '(1)
      (append (genint (- stop 1)) (list stop))))

(defun genpairs (x y)
  (let ((row (mapcar #'(lambda (y)
                        (cons x y))
                        (genint y))))
    (if (= x 0) row
        (append (genpairs (- x 1) y)
                row))))

(genpairs 100 100)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top