Cuál es la diferencia entre la progtwigción declarativa y la imperativa

He estado buscando en la web buscando una definición de progtwigción declarativa e imperativa que arroje algo de luz para mí. Sin embargo, el lenguaje utilizado en algunos de los recursos que he encontrado es desalentador, por ejemplo, en Wikipedia . ¿Alguien tiene un ejemplo del mundo real que puedan mostrarme que pueda traer alguna perspectiva sobre este tema … tal vez en C #.

Un gran ejemplo de C # de progtwigción declarativa vs. imperativa es LINQ.

Con la progtwigción imperativa , le dice al comstackdor lo que quiere que suceda, paso a paso.

Por ejemplo, comencemos con esta colección y elijamos los números impares:

List collection = new List { 1, 2, 3, 4, 5 }; 

Con una progtwigción imperativa, lo solucionaremos y decidiremos lo que queremos:

 List results = new List(); foreach(var num in collection) { if (num % 2 != 0) results.Add(num); } 

Aquí, estamos diciendo:

  1. Crear una colección de resultados
  2. Paso a paso por cada número en la colección
  3. Comprueba el número, si es impar, agrégalo a los resultados

Con la progtwigción declarativa , por otro lado, escribe un código que describe lo que quiere, pero no necesariamente cómo obtenerlo (declare los resultados deseados, pero no paso a paso):

 var results = collection.Where( num => num % 2 != 0); 

Aquí, decimos “Danos todo lo que es raro”, no “Recorre la colección. Comprueba este elemento, si es impar, agrégalo a una colección de resultados”.

En muchos casos, el código será una mezcla de ambos diseños, así que no siempre es en blanco y negro.

La progtwigción declarativa es cuando usted dice lo que quiere, y el lenguaje imperativo es cuando dice cómo obtener lo que quiere.

Un ejemplo simple en Python:

 # Declarative small_nums = [x for x in range(20) if x < 5] # Imperative small_nums = [] for i in range(20): if i < 5: small_nums.append(i) 

El primer ejemplo es declarativo porque no especificamos ningún "detalle de implementación" para comstackr la lista.

Para vincular un ejemplo de C #, generalmente, utilizando los resultados de LINQ en un estilo declarativo, porque no está diciendo cómo obtener lo que desea; solo estás diciendo lo que quieres. Podría decir lo mismo sobre SQL.

Uno de los beneficios de la progtwigción declarativa es que permite al comstackdor tomar decisiones que pueden dar como resultado un código mejor que el que podría obtener a mano. Ejecutando con el ejemplo de SQL, si tuviera una consulta como

 SELECT score FROM games WHERE id < 100; 

el "comstackdor" de SQL puede "optimizar" esta consulta porque sabe que el id es un campo indexado, o tal vez no está indexado, en cuyo caso tendrá que iterar en todo el conjunto de datos de todos modos. O tal vez el motor SQL sabe que este es el momento perfecto para utilizar los 8 núcleos para una búsqueda paralela rápida. Usted , como progtwigdor, no está interesado en ninguna de esas condiciones, y no tiene que escribir su código para manejar ningún caso especial de esa manera.

Declarativo vs. Imperativo

Un paradigma de progtwigción es un estilo fundamental de progtwigción informática. Hay cuatro paradigmas principales: imperativo, declarativo, funcional (que se considera un subconjunto del paradigma declarativo) y orientado a objetos.

Progtwigción declarativa : es un paradigma de progtwigción que expresa la lógica de un cálculo (What do) sin describir su flujo de control (How do). Algunos ejemplos bien conocidos de lenguajes específicos de dominio declarativo (DSL) incluyen CSS, expresiones regulares y un subconjunto de SQL (consultas SELECT, por ejemplo). Muchos lenguajes de marcado como HTML, MXML, XAML, XSLT … a menudo son declarativos. La progtwigción declarativa intenta difuminar la distinción entre un progtwig como un conjunto de instrucciones y un progtwig como una afirmación sobre la respuesta deseada.

Progtwigción imperativa : es un paradigma de progtwigción que describe el cálculo en términos de enunciados que cambian un estado de progtwig. Los progtwigs declarativos se pueden ver doblemente como comandos de progtwigción o aserciones matemáticas.

Progtwigción funcional: es un paradigma de progtwigción que trata la computación como la evaluación de funciones matemáticas y evita datos de estado y variables. Enfatiza la aplicación de funciones, en contraste con el estilo de progtwigción imperativa, que enfatiza los cambios de estado. En un lenguaje funcional puro, como Haskell, todas las funciones carecen de efectos secundarios, y los cambios de estado solo se representan como funciones que transforman el estado.

El siguiente ejemplo de progtwigción imperativa en MSDN , recorre los números del 1 al 10 y encuentra los números pares.

 var numbersOneThroughTen = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //With imperative programming, we'd step through this, and decide what we want: var evenNumbers = new List(); foreach (var number in numbersOneThroughTen) { if (number % 2 == 0) { evenNumbers.Add(number); } } //The following code uses declarative programming to accomplish the same thing. // Here, we're saying "Give us everything where it's odd" var evenNumbers = numbersOneThroughTen.Select(number => number % 2 == 0); 

Ambos ejemplos arrojan el mismo resultado, y uno ni es mejor ni peor que el otro. El primer ejemplo requiere más código, pero el código es comprobable y el enfoque imperativo le otorga un control total sobre los detalles de la implementación. En el segundo ejemplo, el código es posiblemente más legible; sin embargo, LINQ no le da control sobre lo que ocurre detrás de las escenas. Debe confiar en que LINQ proporcionará el resultado solicitado.

Agregaré otro ejemplo que rara vez aparece en la discusión de progtwigción declarativa / imperativa: ¡la interfaz de usuario!

En C #, puede construir una interfaz de usuario usando varias tecnologías.

En el extremo imperativo, puede usar DirectX u OpenGL para dibujar sus botones, casillas de verificación, etc … línea por línea (o realmente, triángulo por triángulo). Depende de usted decir cómo dibujar la interfaz de usuario.

En el final declarativo, tienes WPF. Básicamente, escribe algo de XML (sí, sí, “XAML” técnicamente) y el marco hace el trabajo por usted. Usted dice a qué se parece la interfaz de usuario. Depende del sistema descubrir cómo hacerlo.

De todos modos, solo otra cosa en que pensar. El hecho de que un idioma sea declarativo o imperativo no significa que no tenga ciertas características del otro.

Además, uno de los beneficios de la progtwigción declarativa es que el propósito generalmente se entiende más fácilmente al leer el código, mientras que el imperativo te brinda un control más preciso de la ejecución.

La esencia de todo:

Declarativo -> what que quieres que se haga

Imperativo -> how quieres que se haga

Todas las respuestas anteriores y otras publicaciones en línea mencionan a continuación:

  • Con la progtwigción declarativa , escribes código que describe lo que quieres, pero no necesariamente cómo obtenerlo
  • Deberías preferir la progtwigción declarativa sobre la progtwigción imperativa

Lo que no nos han dicho es cómo lograrlo . Para que parte del progtwig sea más declarativo, otras partes deben proporcionar la abstracción para ocultar los detalles de la implementación (que son los códigos imperativos ).

  • Por ejemplo, LINQ es más declarativo que bucles (para, mientras, etc.), por ejemplo, puede usar list.Where () para obtener una nueva lista filtrada. Para que esto funcione, Microsoft ha hecho todo el trabajo pesado detrás de la abstracción LINQ.

De hecho, una de las razones por la que la progtwigción funcional y las bibliotecas funcionales son más declarativas es porque han abstraído bucles y creado listas, ocultando todos los detalles de implementación (lo más probable es que códigos imperativos con bucles) detrás de la escena.

En cualquier progtwig, siempre tendrá códigos imperativos y declarativos, lo que debe apuntar es ocultar todos los códigos imperativos detrás de las abstracciones, de modo que otras partes del progtwig puedan usarlos declarativamente .

Finalmente, aunque la progtwigción funcional y LINQ pueden hacer que tu progtwig sea más declarativo, siempre puedes hacerlo aún más declarativo al proporcionar más abstracciones. Por ejemplo:

 // JavaScript example // Least declarative var bestProducts = []; for(var i = 0; i < products.length; i++) { var product = products[i]; if (product.rating >= 5 && product.price < 100) { bestProducts.push(product); } } // More declarative var bestProducts = products.filter(function(product) { return product.rating >= 5 && product.price < 100; }); // Most declarative, implementation details are hidden in a function var bestProducts = getBestProducts(); 

La progtwigción imperativa requiere que los desarrolladores definan paso a paso cómo se debe ejecutar el código. Para dar instrucciones de manera imperativa, diga, “vaya a 1st Street, gire a la izquierda en Main, maneje dos cuadras, gire a la derecha en Maple, y pare en la tercera casa a la izquierda”. La versión declarativa podría sonar algo como esto : “Vete a la casa de Sue”. Uno dice cómo hacer algo; el otro dice lo que debe hacerse.

El estilo declarativo tiene dos ventajas sobre el estilo imperativo:

  • No obliga al viajero a memorizar un largo conjunto de instrucciones.
  • Le permite al viajero optimizar la ruta cuando sea posible.

Calvert, C Kulkarni, D (2009). LINQ esencial Addison Wesley. 48.

Me gustó una explicación de un curso de Cambridge + sus ejemplos:

  • Declarativo : especifique qué hacer, no cómo hacerlo
    • Por ejemplo: HTML describe qué debe aparecer en una página web, no cómo debe dibujarse en la pantalla
  • Imperativo : especifique qué y cómo
    • int x; – qué (declarativo)
    • x=x+1; – cómo

La diferencia tiene que ver principalmente con el nivel general de abstracción. Con declaraciones, en algún momento, está tan lejos de los pasos individuales que el progtwig tiene mucha libertad con respecto a cómo obtener su resultado.


Podrías ver cada pieza de instrucción como caer en algún lugar en un continuo:

Grado de abstracción:

 Declarative <<=====|==================>> Imperative 

Ejemplo declarativo del mundo real:

  1. Bibliotecaria, por favor mire una copia de Moby Dick. (El bibliotecario, a su discreción, elige el mejor método para realizar la solicitud)

Ejemplo de Imperative Real World:

  1. Ir a la biblioteca
  2. Buscar sistema de organización del libro (Catálogo de tarjetas – Old school)
  3. Investigue cómo usar catálogos de tarjetas (también se olvidó, derecha)
  4. Descubre cómo están etiquetados y organizados los estantes.
  5. Descubre cómo se organizan los libros en un estante.
  6. Ubicación del libro de referencias cruzadas del catálogo de tarjetas con el sistema de organización para encontrar dicho libro.
  7. Lleve el libro al check-out del sistema.
  8. Echa un vistazo al libro.

En informática, la progtwigción declarativa es un paradigma de progtwigción que expresa la lógica de un cálculo sin describir su flujo de control.

De http://en.wikipedia.org/wiki/Declarative_programming

en pocas palabras, el lenguaje declarativo es más simple porque carece de la complejidad del flujo de control (bucles, declaraciones if, etc.)

Una buena comparación es el modelo ‘código subyacente’ de ASP.Net. Usted tiene archivos declarativos ‘.ASPX’ y luego los archivos de código ‘ASPX.CS’ imperativos. A menudo encuentro que si puedo hacer todo lo que necesito en la mitad declarativa del guión, mucha más gente puede seguir lo que se está haciendo.

La progtwigción imperativa le dice a la computadora explícitamente qué hacer y cómo hacerlo, como especificar el orden y tal

DO#:

 for (int i = 0; i < 10; i++) { System.Console.WriteLine("Hello World!"); } 

Declarativo es cuando le dice a la computadora qué hacer, pero realmente no sabe cómo hacerlo. Datalog / Prolog es el primer idioma que viene a la mente en este sentido. Básicamente todo es declarativo. Realmente no puedes garantizar el orden.

C # es un lenguaje de progtwigción mucho más imperativo, pero ciertas características C # son más declarativas, como Linq

 dynamic foo = from c in someCollection let x = someValue * 2 where c.SomeProperty < x select new {c.SomeProperty, c.OtherProperty}; 

Lo mismo podría escribirse imperativamente:

 dynamic foo = SomeCollection.Where ( c => c.SomeProperty < (SomeValue * 2) ) .Select ( c => new {c.SomeProperty, c.OtherProperty} ) 

(ejemplo de wikipedia Linq)

Robo de Philip Roberts aquí :

  • La progtwigción imperativa le dice a la máquina cómo hacer algo (dando como resultado lo que quiere que suceda)
  • La progtwigción declarativa le dice a la máquina lo que le gustaría que sucediera (y la computadora se da cuenta de cómo hacerlo)

Dos ejemplos:

1. Duplicar todos los números en una matriz

Imperativo:

 var numbers = [1,2,3,4,5] var doubled = [] for(var i = 0; i < numbers.length; i++) { var newNumber = numbers[i] * 2 doubled.push(newNumber) } console.log(doubled) //=> [2,4,6,8,10] 

Declarativamente:

 var numbers = [1,2,3,4,5] var doubled = numbers.map(function(n) { return n * 2 }) console.log(doubled) //=> [2,4,6,8,10] 

2. Sumando todos los artículos en una lista

Imperativo

 var numbers = [1,2,3,4,5] var total = 0 for(var i = 0; i < numbers.length; i++) { total += numbers[i] } console.log(total) //=> 15 

Declarativamente

 var numbers = [1,2,3,4,5] var total = numbers.reduce(function(sum, n) { return sum + n }); console.log(total) //=> 15 

Observe cómo los ejemplos imperativos implican crear una nueva variable, mutarla y devolver ese nuevo valor (es decir, cómo hacer que algo suceda), mientras que los ejemplos declarativos se ejecutan en una entrada dada y devuelven el nuevo valor basado en la entrada inicial (es decir , lo que queremos que suceda).

Solo para agregar otro ejemplo en términos de desarrollo de aplicaciones móviles. En iOS y Android tenemos Interface Builders, donde podemos definir la interfaz de usuario de las aplicaciones.

La UI dibujada usando estos Constructores es de naturaleza declarativa, donde arrastramos y soltamos los componentes. El draeing real ocurre debajo y es realizado por el framework y el sistema.

Pero también podemos dibujar todos los componentes en código, y eso es imperativo en la naturaleza.

Además, algunos lenguajes nuevos, como Angular JS, se centran en el diseño de interfaces de usuario de forma declarativa y es posible que veamos muchos otros idiomas que ofrecen el mismo soporte. Al igual que JAVA no tiene una buena manera declarativa de dibujar aplicaciones de escritorio nativas en JAVA swing o JAVA FX, pero en un futuro cercano podrían hacerlo.

Progtwigción imperativa
Un lenguaje de progtwigción que requiere disciplina de progtwigción como C / C ++, Java, COBOL, FORTRAN, Perl y JavaScript. Los progtwigdores que escriben en dichos idiomas deben desarrollar un orden de acciones adecuado para resolver el problema, basándose en el conocimiento del procesamiento y la progtwigción de datos.

Progtwigción declarativa
Un lenguaje de computadora que no requiere escribir lógica de progtwigción tradicional; Los usuarios se concentran en definir la entrada y la salida en lugar de los pasos del progtwig requeridos en un lenguaje de progtwigción de procedimientos como C ++ o Java.

Los ejemplos declarativos de progtwigción son CSS, HTML, XML, XSLT, RegX.

El progtwig declarativo es solo un dato para su implementación / vm más o menos “universal”.

más: especificar solo un dato, en algún formato codificado (y verificado), 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. El mejor y el más utilizado 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 declarativos 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.

Minuses: adivinas 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 ralentizar todos los demás casos, seguro …

PS Frameworks está a medio 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 …

Me pregunto por qué nadie ha mencionado las clases de atributos como una herramienta de progtwigción declarativa en C #. La popular respuesta de esta página acaba de hablar sobre LINQ como una herramienta de progtwigción declarativa.

De acuerdo con la Wikipedia

Los lenguajes declarativos comunes incluyen los de los lenguajes de consulta de base de datos (por ejemplo, SQL, XQuery), expresiones regulares, progtwigción lógica, progtwigción funcional y sistemas de gestión de configuración.

Entonces, LINQ, como syntax funcional, es definitivamente un método declarativo, pero las clases de atributos en C #, como herramienta de configuración, también son declarativas. Este es un buen punto de partida para leer más al respecto: Descripción general rápida de la progtwigción de atributos C #

Desde mi punto de vista, ambos términos tienen sus raíces en la filosofía, hay tipos de conocimiento declarativos e imperativos. El conocimiento declarativo son afirmaciones de verdad, declaraciones de hechos como axiomas matemáticos. Te dice algo. Imperativo, o conocimiento de procedimiento, te dice paso a paso cómo llegar a algo. Esa es la definición de un algoritmo en esencia. Si lo hiciera, compare un lenguaje de progtwigción de computadora con el idioma inglés. Las oraciones declarativas dicen algo. Un ejemplo aburrido, pero aquí hay una forma declarativa de mostrar si dos números son iguales entre sí, en Java:

 public static void main(String[] args) { System.out.print("4 = 4."); } 

Las oraciones imperativas en inglés, por otro lado, dan una orden o hacen algún tipo de pedido. La progtwigción imperativa, entonces, es solo una lista de comandos (haz esto, haz eso). Aquí hay una forma imperativa de mostrar si dos números son iguales entre sí o no, al aceptar la entrada del usuario, en Java:

 private static Scanner input; public static void main(String[] args) { input = new Scanner(System.in); System.out.println(); System.out.print("Enter an integer value for x: "); int x = input.nextInt(); System.out.print("Enter an integer value for y: "); int y = input.nextInt(); System.out.println(); System.out.printf("%d == %d? %s\n", x, y, x == y); } 

Esencialmente, el conocimiento declarativo omite ciertos elementos para formar una capa de abstracción sobre esos elementos. La progtwigción declarativa hace lo mismo.