Respuesta

6

Si entiendo bien su pregunta, no creo que esto es una regla dura y rápida. Por ejemplo, puede usar un lenguaje funcional como Lisp, para crear un intérprete para sí mismo. En este caso, los detalles de implementación se implementan de una manera funcional (porque Lisp es un lenguaje funcional).

Además, si tiene un lenguaje que es Turing Complete, puede usarlo para implementar un analizador/intérprete/compilador para cualquier otro idioma. Hay lenguajes imperativos de Turing-Complete y lenguajes de Turing-Complete funcionales/declarativos.

Pero todos los códigos eventualmente se envían al código de ensamblaje o máquina, que es inherentemente imprescindible. En teoría, lo que dije antes es cierto, pero aparentemente no en la práctica :).

Como un lado histórico interesante, LISP fue una construcción completamente teórica; era una notación matemática para los lenguajes de computadora. Se mantuvo hasta que la función teórica de LISP eval fue implementado en código de máquina por Steve Russel en un IBM 704:

De acuerdo con lo informado por Paul Graham en Los hackers & pintores, p. 185, McCarthy dijo: "Steve Russell dijo, mira, ¿por qué no programo este eval ..., y le dije, ho, ho, estás confundiendo la teoría con la práctica, esta eval está diseñada para leyendo, no para computar. Pero siguió adelante y lo hizo. Es decir, compiló la evaluación en mi documento en el código de máquina IBM 704, corrigió errores, y luego publicitó esto como un intérprete de Lisp, que sin duda era así. ese punto Lisp tenía esencialmente la forma que tiene hoy ... " (énfasis mío)

Así que una vez más, las sutilezas entre la teoría y la práctica. :)

+0

Tiene razón, este es el significado de la pregunta. – AwkwardCoder

+0

Pero el intérprete Lisp se implementa en términos de código imperativo. En algún momento, a menos que esté ejecutando en una máquina Lisp, las cosas deben compilarse para el ensamblaje. – dsimcha

+0

Aludí a eso al final de mi respuesta. Si lo piensas * teóricamente * entonces tiene sentido. Pero en la práctica, no es así. Por ejemplo, podría implementar un analizador LISP en Perl y un analizador Perl en LISP. Si lo ves en papel, en el primer caso estás viendo un lenguaje funcional que se está implementando de manera imperativa, mientras que en el segundo caso, estás viendo un lenguaje imperativo que se implementa de una manera funcional. Sin embargo, cuando lo ponga en práctica, obviamente será imprescindible, porque el lenguaje ensamblador es imprescindible. –

3

La máquina de bajo nivel (CPU, nivel de lenguaje ensamblador) es imprescindible, por lo que obviamente en algún momento la implementación tendrá que tener esto en cuenta. Sin embargo, Implementing certain kinds of functional languages like Haskell toma algunos enfoques no obvios para crear un tiempo de ejecución con un rendimiento decente.

Por extraño que parezca, los idiomas más imperativas pasan por una fase en la que todo el código se transforma para ser más declarativa:

Aquí es un ejemplo de la compilación Esquema (funcional) directamente código C (imperativo):

2

Su pregunta no está nada clara. Debajo del capó, las instrucciones del procesador son imperativas en la naturaleza. Si se supone que su código se ejecuta en una máquina de von Neumann, finalmente debería ejecutarse como código imperativo.

Es posible construir una máquina (con alguna arquitectura específica) que soporte inherentemente esas operaciones. De hecho, LispM había sido diseñado para ayudar a ejecutar programas Lisp. Si bien no estoy familiarizado con las características de hardware de LispM, probablemente califica como que proporciona algunas operaciones primitivas en un nivel más declarativo.

2

¿Los lenguajes declarativos se construyen a partir de operadores imperativos & funciones?

A veces. Es una propiedad de la implementación , no el idioma.

En la década de 1980, muchas personas compilaron programas funcionales para gráficos, luego reescribieron los gráficos en gráficos más simples. Este cálculo usualmente involucraba actualizar los gráficos en su lugar, pero de lo contrario era tan declarativo como quisieras. Para obtener más información, busque "reducción de gráficos" o lea "El motor de reducción de cuatro tiempos" de Chris Clack y Simon Peyton Jones.

Finalmente, los escritores de compiladores descubrieron formas de obtener un mejor rendimiento compilando programas funcionales directamente en el código máquina nativo. Si la máquina nativa es una máquina básica típica, esto significa operaciones imperativas típicas. Sin embargo, si busca el trabajo pionero del Profesor Arvind en MIT, su grupo diseñó y construyó máquinas de flujo de datos donde las operaciones computacionales fundamentales son de carácter más declarativo. Fue un gran trabajo, pero todas las arquitecturas de propósito especial que florecieron en la década de 1980 se extinguieron gracias al gran ciclo virtuoso de Microsoft/Intel (más software -> más PC vendidas -> procesadores más baratos -> más PC vendidas -> ... . -> netbooks de $ 300 que hacen cosas geniales).

0

implementación es que 'oculto bajo el capó. se puede construir con cualquier paradigma.

programa declarativo es solo un dato por su implementación algo más o menos "universal"/vm.

pluses: especificar solo un dato, en algunos formatos codificados (y comprobados), es más simple y menos propenso a errores que especificar la variante de algún algoritmo imperativo directamente. algunas especificaciones complejas simplemente no se pueden escribir directamente, solo en alguna forma de DSL. mejor y las frecuencias utilizadas en las estructuras de datos DSL son conjuntos y tablas. porque no tienes dependencias entre elementos/filas. y cuando no tiene dependencias tiene la libertad de modificar y facilitar el soporte.(compare, por ejemplo, módulos con clases, con módulos felices y con clases tiene un problema de clase base frágil) todos los bienes de declarativo y DSL se sigue inmediatamente de los beneficios de esas estructuras de datos (tablas y conjuntos). otra ventaja: puede cambiar la implementación del lenguaje declarativo vm, si DSL es más o menos abstracto (bien diseñado). hacer una implementación paralela, por ejemplo. o transfiéralo a otro sistema operativo, etc. todas las interfaces o protocolos de aislamiento modulares bien especificados le brindan tanta libertad y facilidad de soporte.

menos: supongo que está bien. la implementación del algoritmo imperativo/vm genérico (y parametrizado por DSL) puede ser más lenta y/o tener menos memoria que la específica. en algunos casos. si esos casos son raros, solo olvídate, que sea lento. si es frecuente, siempre puede extender su DSL/vm para ese caso. en algún lugar ralentizando todos los demás casos, seguro ...

P.S. Frameworks está a mitad de camino entre DSL e imperativo. y como todas las soluciones intermedias ... combinan deficiencias, no beneficios. no son tan seguros Y no tan rápidos :) mira a Haskell Jack-of-All-Trades - está a medio camino entre ML fuerte y simple y metaprog flexible Prolog y ... qué monstruo es. puede ver Prolog como un Haskell con funciones/predicados solo booleanos. y cuán simple es su flexibilidad contra Haskell ...

Cuestiones relacionadas