Pregunta

Tengo algo de código que recoge los puntos (consed enteros) de un bucle que se ve algo como esto:

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

Mi pregunta es, ¿es correcto usar `(,x . ,y) en esta situación?

Editar:Este ejemplo no es acerca de la generación de una tabla de 100x100 elementos, el código está aquí sólo para ilustrar el uso de dos bucle de variables y la consing de sus valores.He editado el lazo para hacer esto en claro.El real bucle que se utilice depende de varias otras funciones (y es parte de uno mismo) por lo que tiene más sentido para reemplazar las llamadas con literales enteros y a tirar el lazo de salida de la función.

¿Fue útil?

Solución

Sería mucho "mejor" que acaba de hacer (cons x y).

Pero a responder a la pregunta, no hay nada de malo en hacerlo :) (excepto lo que es un pelín más lento).

Otros consejos

Creo que la respuesta aquí es la utilización de los recursos (después de Este post)

por ejemplo, en 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:hay un par de cosas extrañas acerca de su código aquí.Tenga en cuenta que

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

es equivalente a:

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

lo que probablemente no es lo que pretende.Note tres cosas:En primer lugar, la forma en que ha escrito, x e y tienen la misma función.Usted probablemente significaba para anidar bucles.Segundo, su hacer después de la y es incorrecto, ya que no hay lisp forma siguiente.En tercer lugar, tienes razón que usted podría utilizar el acento grave enfoque aquí pero hace que su código sea más difícil de leer y no idiomático no hay ganancia, por lo que lo mejor es evitarlo.

Adivinar lo que en realidad pretende, usted podría hacer algo como esto (usando loop):

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

Si no te gusta el bucle macro (como Kyle), puede utilizar otra iteración de construcción como

(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))

Si usted se encuentra haciendo este tipo de cosas mucho, probablemente debería escribir más general de la función para el cruce de listas, a continuación, pasar estas listas de enteros

Si realmente tienes un problema con el iteración, no solo bucle, se puede hacer este tipo de cosas de forma recursiva (pero tenga en cuenta, esto no es plan, su ejecución no garantiza TCO).La función "genint" demostrado por Kyle aquí es una variante de un común (pero no estándar) función de iota.Sin embargo, anexando a la lista es una mala idea.Un equivalente de la aplicación como esta:

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

debería ser mucho más eficiente, pero aún no es una cola de llamadas.Nota: he puesto esto para el más habitual basado en 0, pero dado que un parámetro opcional que empieza a la 1 o a cualquier otro número entero.Por supuesto, lo anterior puede ser escrito algo así como:

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

Que tiene la ventaja de no soplar la pila para grandes argumentos.Si su aplicación soporta la cola de llamadas eliminación, también puede evitar la recursividad se ejecuta fuera de lugar por hacer algo como esto:

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

Espero que ayude!

¿Por qué no

(cons x y)

Por cierto, he intentado ejecutar el código en CLISP y no funcionó como se esperaba.Porque yo no soy un gran fan de el bucle macro he aquí cómo usted puede conseguir lo mismo de forma recursiva:

(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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top