¿Por qué todas las lambdas en The Little Schemer?
the-little-schemer (6)
Después de aprender un poco de Scheme de SICP, comencé a leer The Little Schemer (que me parece bastante entretenido) y casi una cuarta parte está lista. Me di cuenta de que puedo escribir muchas soluciones (¿la mayoría? ¿Todas?) Sin usar lambda, mientras que The Little Schemer siempre las usa. Por ejemplo, la primera definición es
(define atom?
(lambda (x)
(and (not (pair? x)) (not (null? x)))))
que, a menos que me equivoque, se puede escribir más simplemente como
(define (atom? x)
(and (not (pair? x)) (not (null? x))))
¿Me estoy perdiendo algo fundamental si escribo soluciones sin lambda?
Estoy leyendo un poco sobre cálculo lambda (leyendo "La implementación de los lenguajes de programación funcionales" de Simon Peyton Jones; pdf gratuito en línea) mientras uso TLS. Y, entonces, esto es solo una conjetura, pero creo que los autores de TLS quieren que realmente te sientas pesado en tus pensamientos. No salen y lo dicen, pero hay indicios (consulte la página 107 de TLS) de que todo esto es solo un ejercicio de calculo lambda aplicado. Así que tal vez estén diciendo sin decir: "¡Estás haciendo abstracciones lambda, mi amigo!"
Originalmente, define
tenía una sintaxis única, para establecer una variable en un valor. Ese es el estilo usado en libros tan antiguos (y atemporales). Más adelante, define
tiene una sintaxis diferente como acceso directo, que es la que estás usando.
Solo por diversión, busque en sus bibliotecas Scheme, puede encontrar una macro que expanda la forma no-lambda a la antigua lambda-heavy.
Puede ver lo que su Esquema expande estos accesos directos (macros) para usar expand
(si es compatible):
mzscheme 4.2.4 (con DrScheme):
> (expand ''(define (add1 x) (+ 1 x)))
#<syntax (define-values (add1) (lambda...>
(define-values
(add1)
(lambda (x) (apply + ''1 x)))
Esquema de Chez 8.0:
> (expand ''(define (add1 x) (+ 1 x)))
(begin
(set! add1
(lambda (x)
(+ 1 x)))
(void))
La lambda
aparece llana como el día.
Recuerdo vagamente a un profesor discutiendo algo como esto.
Creo que la solución lambda se utiliza por dos razones:
Lo primero es algo puramente histórico. En un momento dado, esa era la única manera en que era posible. Así que algunas personas todavía usan ese método.
La segunda es que a algunas personas les gusta ser más explícitas sobre el hecho de que se está creando una función, por lo que les gusta ver la palabra lambda.
Así que creo que la elección se reduce a lo que más te guste personalmente.
The Little Schemer utiliza un esquema de pseudo-código (para hacer simplificaciones con fines educativos y para ser independiente de la implementación). El esquema estándar de hoy tiene una definición de definición en la que usted está invocando implícitamente a lambda (consulte http://www.cs.cmu.edu/Groups/AI/html/r4rs/r4rs_7.html ). El esquema de Little Schemer es muy simple y no incluye esta forma alternativa.
Yo prefiero el estilo lambda
para la enseñanza, ya que hace que la creación de funciones sea más explícita, como dice Jay.
¿Al aprender, las funciones simples con las que empiezas como atom?
Se define
d en el nivel superior. Esto significa que es posible, y aún más compacto, crear la función con el estilo de define
que mencionas.
Sin embargo, cuando comienzas a usar funciones como valores de primera clase, por ejemplo, como un argumento para map
, verás lambda
por primera vez, y podría parecer más extraño y más mágico de lo que realmente es.
En cambio, si ha estado definiendo sus funciones con lambda
todo el tiempo, es menos importante ver que las funciones son como cualquier otro valor. Resulta que están en el lado derecho de define
bastante frecuencia, pero no son diferentes de un número o una constante citada:
(define x 1)
(define l ''(2 3 4 5))
(define s (cons x ls))
(define f (lambda (n) (+ n 2)))
Por supuesto, el lenguaje es compatible con ambas formas, por lo que eventualmente se reduce al estilo. Para mí, hay una coherencia atractiva en el uso de define
cuando todas sus funciones se realizan con lambda
: el primer argumento es siempre un símbolo, y el segundo es cualquier expresión antigua. Y el hecho de que lambda
es como cualquier expresión antigua es una de las cosas más importantes que debe aprender cualquier programador funcional.