c# - tipos - ¿Cuál es la diferencia entre programación declarativa e imperativa?




programacion imperativa tipos de datos (11)

He estado buscando en la web una definición de programación declarativa e imperativa que me arrojaría algo de luz. 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 pueda mostrarme que pueda aportar alguna perspectiva a este tema (quizás en C #)?


En informática, la programación declarativa es un paradigma de programación que expresa la lógica de una computación 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 de "código subyacente" de ASP.Net. Tiene archivos declarativos '.ASPX' y luego los imperativos archivos de código 'ASPX.CS'. A menudo encuentro que si puedo hacer todo lo que necesito en la mitad declarativa del guión, muchas más personas pueden seguir lo que se está haciendo.


La programación imperativa requiere que los desarrolladores definan paso a paso cómo se debe ejecutar el código. Para dar direcciones de manera imperativa, usted dice: "Vaya a 1st Street, gire a la izquierda en Main, conduzca dos cuadras, gire a la derecha en Maple, y pare en la tercera casa a la izquierda". La versión declarativa puede sonar como esta : "Conduce a la casa de Sue". Uno dice cómo hacer algo; el otro dice lo que hay que hacer.

El estilo declarativo tiene dos ventajas sobre el estilo imperativo:

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

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


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

En C #, puedes construir una UI usando varias tecnologías.

En el extremo imperativo, puede usar DirectX u OpenGL para dibujar de manera muy imperativa 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 extremo declarativo, tienes WPF. Básicamente, escribes algunos XML (sí, sí, "XAML" técnicamente) y el marco hace el trabajo por ti. Usted dice cómo se ve la interfaz de usuario. Depende del sistema averiguar cómo hacerlo.

De todos modos, sólo 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, un beneficio de la programación declarativa es que el propósito generalmente se comprende más fácilmente al leer el código, mientras que el imperativo le brinda un control más preciso sobre la ejecución.

La esencia de todo:

Declarativo -> what que quieres hacer

Imperativo -> how quieres que se haga


Declarativo vs Imperativo

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

Programación declarativa : es un paradigma de programación que expresa la lógica de una computación (Qué hacer) sin describir su flujo de control (Cómo hacerlo). Algunos ejemplos bien conocidos de lenguajes declarativos específicos de dominio (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 programación declarativa intenta difuminar la distinción entre un programa como un conjunto de instrucciones y un programa como una afirmación sobre la respuesta deseada.

Wikipedia : es un paradigma de programación que describe el cálculo en términos de declaraciones que cambian el estado de un programa. Los programas declarativos se pueden ver dualmente como comandos de programación o afirmaciones matemáticas.

Programación funcional: es un paradigma de programación que trata la computación como la evaluación de funciones matemáticas y evita los datos de estado y mutables. Enfatiza la aplicación de funciones, en contraste con el estilo de programación imperativo, que enfatiza los cambios en el 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 programación imperativa en MSDN , recorre los números del 1 al 10 y encuentra los números pares.

var numbersOneThroughTen = new List<int> { 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<int>();
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 dan el mismo resultado, y uno no es ni 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 da 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 sucede detrás de la escena. Debe confiar en que LINQ proporcionará el resultado solicitado.


La programació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 construir la lista.

Para vincular un ejemplo de C #, en general, el uso de LINQ da como resultado un estilo declarativo, porque no está diciendo cómo obtener lo que desea; Sólo estás diciendo lo que quieres. Se podría decir lo mismo de SQL.

Uno de los beneficios de la programación declarativa es que le permite al compilador tomar decisiones que podrían resultar en un mejor código que el que podría tomar a mano. Ejecutando con el ejemplo de SQL, si tuviera una consulta como

SELECT score FROM games WHERE id < 100;

el "compilador" de SQL puede "optimizar" esta consulta porque sabe que id es un campo indexado, o tal vez no esté indexado, en cuyo caso de todas formas tendrá que iterar sobre todo el conjunto de datos. 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 programador, no está preocupado por ninguna de esas condiciones, y no tiene que escribir su código para manejar un caso especial de esa manera.


La programación imperativa es decirle a la computadora explícitamente qué hacer y cómo hacerlo, como especificar el orden y cosas así.

DO#:

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

Declarativo es cuando le dices a la computadora qué hacer, pero no realmente cómo hacerlo. Datalog / Prolog es el primer lenguaje que viene a la mente a este respecto. Básicamente todo es declarativo. Realmente no se puede garantizar el orden.

C # es un lenguaje de programación mucho más imperativo, pero ciertas características de 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)


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

Segun wikipedia

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

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


Robando a Philip Roberts aquí :

  • La programación imperativa le dice a la máquina cómo hacer algo (que resulta en lo que quieres que suceda)
  • La programació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

Imperativamente:

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 elementos en una lista

Imperativamente

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 suceda algo), mientras que los ejemplos declarativos se ejecutan en una entrada determinada y devuelven el nuevo valor en función de la entrada inicial (es decir, , lo que queremos que suceda).


Todas las respuestas anteriores y otras publicaciones en línea mencionan lo siguiente:

  • Con la programación declarativa , usted escribe un código que describe lo que quiere, pero no necesariamente cómo obtenerlo.
  • Prefiere la programación declarativa a la imperativa.

Lo que no nos han dicho es cómo lograrlo . Para que parte del programa 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 los bucles (para, while, 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 de LINQ.

De hecho, una de las razones por las que la programación funcional y las bibliotecas funcionales son más declarativas es porque han extraído los bucles y creaciones de la lista, ocultando todos los detalles de la implementación (probablemente códigos imperativos con bucles) detrás de la escena.

En cualquier programa, siempre tendrá códigos tanto imperativos como declarativos, lo que debe buscar es ocultar todos los códigos imperativos detrás de las abstracciones, de modo que otras partes del programa puedan usarlos de forma declarativa .

Finalmente, aunque la programación funcional y LINQ pueden hacer que su programa sea más declarativo, siempre puede 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();

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

Con la programación imperativa , le dices al compilador lo que quieres que suceda, paso a paso.

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

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

Con la programación imperativa, pasaríamos por esto y decidiríamos lo que queremos:

List<int> results = new List<int>();
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 través de cada número en la colección
  3. Verifique el número, si es impar, agréguelo a los resultados.

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

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

Aquí, estamos diciendo "Danos todo donde sea extraño", no "Paso a través de la colección. Revisa este elemento, si es extraño, agrégalo a una colección de resultados".

En muchos casos, el código también será una mezcla de ambos diseños, por lo que no siempre es blanco y negro.


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

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

Ejemplos de programación declarativos son CSS, HTML, XML, XSLT, RegX.





declarative-programming