2011-01-24 31 views
18

Después de aprender un poco de Scheme de SICP, comencé a leer The Little Schemer (que encuentro bastante entretenido) y estoy casi un cuarto hecho. Me di cuenta de que puedo escribir muchas (¿la mayoría?) Soluciones sin usar lambda, mientras que The Little Schemer siempre las usa. Por ejemplo, la primera definición es¿Por qué todas las lambdas en The Little Schemer?

(define atom? 
    (lambda (x) 
    (and (not (pair? x)) (not (null? x))))) 

el cual, si no me equivoco, 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 lambda-menos?

+5

lambda es el alfa y omega – eljenso

Respuesta

14

Originalmente, define tenían una sintaxis simple, para establecer una variable a un valor. Ese es el estilo utilizado en libros tan antiguos (y atemporales). Más tarde, define obtuvo una sintaxis diferente como acceso directo, que es el que estás usando.

Sólo por diversión, buscar en sus bibliotecas Scheme, es posible encontrar una macro que se expande la forma no-lambda en el anterior lambda-pesado.

+9

No realmente - el "nuevo" formulario 'define' ha estado en el idioma desde el primer informe revisado, en 1978. La elección de usar lambdas explícitas en el libro es un estilo/pedagógico uno. –

+0

no sabía eso ... pero verificando la primera edición (llamada "Little LISPer" originalmente) fue lanzada en 1974 – Javier

+1

Sí, pero la versión de Lisp es irrelevante ya que no hay tal opción allí ... –

4

Recuerdo vagamente un profesor hablando de algo como esto.

Creo que la solución lambda se utiliza por dos razones:

El primero es puramente una cosa histórica. En un momento dado, esa era la única forma en que era posible. Entonces algunas personas aún usan ese método.

La segunda es que algunas personas como para ser más explícito sobre el hecho de que se está creando una función, por lo que les gusta ver la palabra lambda.

Así que creen que la elección se reduce a lo que sea que personalmente me gusta el mejor.

1

El pequeño Schemer utiliza un esquema de pseudo-código (para hacer simplificaciones para los propósitos educativos y ser independiente de la implementación). El Esquema estándar de hoy tiene una definición de definir en la que está invocando implícitamente a lambda (vea 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.

22

prefiero fuertemente el estilo -Heavy lambda para la enseñanza, ya que hace que la creación de la función más explícita, como dice Jay.

Al aprender, las funciones simples con las que comienza con atom? son define d en el nivel superior. Esto significa que es posible, y aún más compacto, crear la función con el defun-style define que mencionas.

Sin embargo, cuando empiece a usar funciones como valores de primera clase, por ejemplo, como un argumento para map, verá el lambda por primera vez, y podría parecer más extraño y mágico de lo que realmente es.

En lugar de eso, si ha definido sus funciones con lambda todo el tiempo, es menos que un salto para ver que las funciones son como cualquier otro valor.Que se encuentren en el lado derecho de la define con bastante frecuencia, pero no son diferentes de un número o una constante citado:

(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 se reduce a estilo, finalmente, . Para mí, hay una consistencia atractiva en el uso de define cuando todas sus funciones están hechas con lambda: el primer argumento es siempre un símbolo, y el segundo argumento es cualquier expresión anterior. Y el hecho de que lambda es como cualquier expresión antigua es una de las cosas más importantes que cualquier programador funcional debe aprender.

+6

+1 Es refrescante para pensar en declarar funciones de la misma manera que declaras las variables: nombre a la izquierda, valor a la derecha. – erjiang

+0

Gracias por destacar el aspecto de consistencia de este enfoque; complementa la otra explicación. –

+2

"Y el hecho de que lambda sea como cualquier expresión anterior es una de las cosas más importantes que cualquier programador funcional debe aprender" - esto no estaba claro para mí hasta que leí tu explicación. –

8

Se puede ver lo que su esquema se expande estos accesos directos (macros) en el uso de 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))) 

Chez Esquema 8.0:

> (expand '(define (add1 x) (+ 1 x))) 
(begin 
    (set! add1 
    (lambda (x) 
     (+ 1 x))) 
    (void)) 

El lambda aparece como un día.

+3

¡Solo sirve para mostrar cuán importantes son las macros en Scheme, incluso 'define' es una macro! – acfoltzer

+0

Esto es muy útil para ayudar a entender, gracias. –

2

Estoy leyendo un poco sobre cálculo lambda (leyendo "La implementación de lenguajes de programación funcional" por Simon Peyton Jones, pdf gratuito en línea) cuando uso TLS. Y, por lo tanto, esto es sólo una suposición, pero creo que los autores de TLS quieren que realmente seas demasiado pesado en tu forma de pensar. No salen y lo dicen, pero hay indicios (consulte la página 107 de TLS) de que todo esto es solo un ejercicio de lambda calc aplicada. Así que tal vez están diciendo sin decir: "¡Estás haciendo abstracciones lambda, mi amigo!"

Cuestiones relacionadas