variables - programacion - lenguajes de programación lisp y prolog
Separar espacios de nombres para funciones y variables en Common Lisp versus Scheme (6)
Scheme usa un solo espacio de nombres para todas las variables, independientemente de si están vinculadas a funciones u otros tipos de valores. Common Lisp separa los dos, de modo que el identificador "hello" puede referirse a una función en un contexto y una cadena en otro.
(Nota 1: esta pregunta necesita un ejemplo de lo anterior; siéntase libre de editarla y agregar una, o envíela por correo electrónico al autor original y yo lo haré).
Sin embargo, en algunos contextos, como pasar funciones como parámetros a otras funciones, el programador debe distinguir explícitamente que está especificando una variable de función, en lugar de una variable que no funciona, usando #''
, como en:
(sort (list ''(9 A) ''(3 B) ''(4 C)) #''< :key #''first)
Siempre he considerado que esto es un poco vergonzoso, pero recientemente me encontré con un argument que esto es realmente una característica:
... la distinción importante reside realmente en la sintaxis de las formas, no en el tipo de objetos. Sin saber nada sobre los valores de tiempo de ejecución involucrados, está bastante claro que el primer elemento de una forma de función debe ser una función. CL toma este hecho y lo convierte en una parte del lenguaje, junto con las formas macro y especiales que también pueden (y deben) determinarse estáticamente. Entonces mi pregunta es: ¿por qué querría que los nombres de las funciones y los nombres de las variables estuvieran en el mismo espacio de nombres, cuando el uso principal de los nombres de las funciones debe aparecer donde raramente querría aparecer un nombre de variable?
Considere el caso de los nombres de clase: ¿por qué una clase llamada FOO debería evitar el uso de variables llamadas FOO? La única vez que me referiré a la clase con el nombre FOO es en contextos que esperan un nombre de clase. Si, en la rara ocasión que necesito obtener el objeto de clase que está vinculado al nombre de clase FOO, hay FIND-CLASS.
Este argumento tiene algún sentido para mí a partir de la experiencia; hay un caso similar en Haskell con nombres de campo, que también son funciones utilizadas para acceder a los campos. Esto es un poco incomodo
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
Esto se resuelve con un poco de sintaxis adicional, especialmente agradable gracias a la extensión NamedFieldPuns
:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
Entonces, a la pregunta, más allá de la coherencia, ¿cuáles son las ventajas y desventajas, tanto para Common Lisp vs. Scheme como en general, de un solo espacio de nombres para todos los valores versus valores separados para funciones y valores no funcionales?
El mayor inconveniente que veo, al menos para Common Lisp, es la comprensibilidad. Todos podemos estar de acuerdo en que usa diferentes espacios de nombres para variables y funciones, pero ¿cuántos tiene? En PAIP, Norvig demostró que tiene "al menos siete" espacios de nombres.
Cuando uno de los libros clásicos del idioma, escrito por un programador muy respetado, ni siquiera puede decirlo con certeza en un libro publicado, creo que hay un problema. No tengo problemas con varios espacios de nombres, pero desearía que el lenguaje fuera, al menos, lo suficientemente simple como para que alguien pudiera entender este aspecto por completo.
Me siento cómodo usando el mismo símbolo para una variable y para una función, pero en las áreas más oscuras recurro a usar diferentes nombres por miedo (colisionar espacios de nombres puede ser realmente difícil de depurar), y eso realmente nunca debería ser el caso.
El nombre de una función en Scheme es solo una variable con la función como su valor. Ya sea que lo haga (define x (y) (zy))
o (let ((x (lambda (y) (zy))))
, estoy definiendo una función a la que puedo llamar. Así que la idea de que "un nombre de variable" Raramente querría aparecer allí "es algo engañoso en lo que respecta a Scheme.
El esquema es un lenguaje característicamente funcional, por lo que tratar las funciones como datos es uno de sus principios. Tener funciones como un tipo propio que se almacena como todos los demás datos es una forma de llevar a cabo la idea.
En realidad, como se describe en el documento de Richard Gabriel y Kent Pitman , el debate es sobre Lisp-5 contra Lisp-6, ya que hay varios otros espacios de nombres allí, en el documento se mencionan nombres de tipos, nombres de etiquetas, nombres de bloques y nombres de declaración. editar: esto parece ser incorrecto, como Rainer señala en el comentario: Scheme en realidad parece ser un Lisp-1. Sin embargo, lo siguiente no se ve afectado en gran medida por este error.
Si un símbolo denota algo para ser ejecutado o algo a lo que referirse siempre está claro desde el contexto. Lanzar funciones y variables en el mismo espacio de nombres es principalmente una restricción: el programador no puede usar el mismo nombre para una cosa y una acción. Lo que saca un Lisp-5 de esto es que se evita una sobrecarga sintáctica para hacer referencia a algo de un espacio de nombre diferente de lo que implica el contexto actual. editar: esta no es la imagen completa, solo la superficie.
Sé que a los proponentes de Lisp-5 les gusta el hecho de que las funciones son datos, y que esto se expresa en el núcleo del lenguaje. Me gusta el hecho de que puedo llamar a una "lista" de listas y un "automóvil" de automóvil sin confundir mi compilador, y las funciones son, de todos modos, un tipo de datos fundamentalmente especial. editar: este es mi punto principal: espacios de nombres separados no son una verruga en absoluto.
También me gustó lo que Pascal Constanza dijo sobre esto.
Hay cosas buenas para ambos enfoques. Sin embargo, creo que cuando importa, prefiero tener una LISTA de función y una LISTA variable que tener que deletrear una de ellas incorrectamente.
Los dos enfoques diferentes tienen nombres: Lisp-1 y Lisp-2. Un Lisp-1 tiene un único espacio de nombres para las variables y funciones (como en Scheme), mientras que un Lisp-2 tiene espacios de nombres separados para variables y funciones (como en Common Lisp). Menciono esto porque es posible que no conozca la terminología ya que no se refirió a ella en su pregunta.
Wikipedia se refiere a este debate :
Si un espacio de nombres separado para las funciones es una ventaja es una fuente de contención en la comunidad Lisp. Por lo general, se lo conoce como el debate Lisp-1 vs. Lisp-2. Lisp-1 se refiere al modelo de Scheme y Lisp-2 se refiere al modelo de Common Lisp. Estos nombres fueron acuñados en un documento de 1988 por Richard P. Gabriel y Kent Pitman, que compara ampliamente los dos enfoques.
El artículo de Gabriel y Pitman titulado Problemas técnicos de separación en células de función y células de valor aborda este mismo tema.
Me he encontrado con una distinción similar en Python (espacio de nombre unificado) frente a Ruby (espacios de nombres distintos para métodos vs no métodos). En ese contexto, prefiero el enfoque de Python; por ejemplo, con ese enfoque, si quiero hacer una lista de cosas, algunas de las cuales son funciones mientras que otras no, no tengo que hacer nada diferente con sus nombres. , dependiendo de su "función-ness", por ejemplo. Se aplican consideraciones similares a todos los casos en los que los objetos de función se deben agrupar en lugar de invocarse (argumentos a, y devolver valores desde, funciones de orden superior, etc., etc.).
También se pueden llamar las no-funciones (si sus clases definen __call__
, en el caso de Python - un caso especial de "sobrecarga del operador") por lo que la "distinción contextual" tampoco es necesariamente clara.
Sin embargo, mi experiencia de "lisp-oid" es / estaba principalmente con Scheme en lugar de Common Lisp, por lo que puedo estar subconscientemente influenciado por la familiaridad con el espacio de nombres uniforme que al final proviene de esa experiencia.