2011-05-02 19 views
7

que estaba tratando con el siguiente código en el esquema de la raqueta y el MIT, me sorprende que el compilador de tiro errar¿Cómo comprobar si una lista contiene sólo #t

(foldr and #t '(#t #t #f)) 

¿Hay alguna manera de utilizar reducir/camino veces para verificar si una lista contiene solo verdadero o falso? Sé que una lambda puede hacer el trabajo, pero realmente nos preguntamos por qué este no es un código válido. Recuerdo que puedo hacerlo en Haskell .....

TIA.

+0

¿Qué mensaje de error obtuvo? – brandizzi

+0

Scheme and Racket no son exactamente iguales, pero puede encontrar una solución en [Using AND with the apply function in Scheme] (http://stackoverflow.com/q/387775/1281433). –

Respuesta

8

and es una macro, por lo que no tiene un valor en sí mismo. Específicamente, cortocircuita la evaluación, y usarla como lo intentaste no tendrá ningún sentido. Por esa razón, Racket tiene andmap que puede usar en tales casos. (Otras implementaciones tienen una funcionalidad similar con nombres diferentes - por ejemplo, SrfI-1 utiliza every.)

+0

La evaluación de cortocircuito no implica necesariamente que no se pueda plegar. El OP no está pidiendo efectos secundarios. Si 'y' el valor de inicialización y el primer elemento, debería obtener un verdadero o falso. 'y'ing eso con el segundo elemento debería hacer lo mismo, etc. – drysdam

+0

No, no implica no poder doblar * si * estás dispuesto a aceptar eso' (y ...) 'en una forma y un 'y' independiente tienen una semántica diferente. La opción abrumadoramente popular fue evitar tal confusión. Considere el hecho de que en cualquier implementación de Scheme que tenga macros de identificación (Racket incluida) es extremadamente fácil implementar un 'y' de doble cara, y que el problema dista mucho de ser uno que nunca se discutió. –

+0

Luego está la otra salida: (intente) que las formas 'y' compartan la misma semántica, otra idea bien pillada ... Por un lado, usted obtiene algunas sorpresas (ya sea' foldl' se convierte en una forma especial, o vuelves al comportamiento de no cortocircuito), y en el lado más importante, llegas a ... fexprs, y toda la diversión que eso implica. –

1

Esto funciona por engaño;

(primitive-eval (cons 'and '(#t #f))) 
+0

Eso funciona en muchas implementaciones (en Racket usarías 'eval'), pero es una mala idea por otras razones. (Por ejemplo, o tragas la sorpresa de que '(let ((x 1)) (eval (cons 'y' (x))))' no funciona, o evitas tales cosas que te dejan con 'andmap'/'every' -like funcionalidad.) –

+0

Seguramente si construí la lista * como una cadena * y luego evalué la cadena, funcionaría. Pensé que el objetivo de lisp era que el programa y los datos son lo mismo. – drysdam

+0

No, la evaluación del código de una cadena tiene exactamente los mismos problemas.Lo que quise decir al evitarlos es evitar cualquier referencia a enlaces, y eso te deja con la capacidad simple de reducir una lista de valores de la misma forma que lo hace 'andmap'. –

7

Y es una macro y no se puede utilizar como una función. Póngalo en una función:

(foldr (lambda (a b) (and a b)) #t '(#t #t #f))

1

Una cosa que podría estar fuera es que en la raqueta y del esquema, los verdaderos valores son distintos de #f nada. Debido a que su pregunta se refiere booleanos, lo siguiente será más exigente:

#lang racket 
(define (boolean-true? x) (eq? x #t)) 
(define (only-contains-#t? l) 
    (andmap boolean-true? l)) 

Por ejemplo,

> (only-contains-#t? '()) 
#t 
> (only-contains-#t? '(#t #t #t)) 
#t 
> (only-contains-#t? '(#t #t true)) 
#f 
Cuestiones relacionadas