c# - son - programacion imperativa
¿Cuál es la diferencia entre programación declarativa e imperativa? (16)
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.
A mi entender, ambos términos tienen raíces en la filosofía, existen tipos de conocimiento declarativo e imperativo. El conocimiento declarativo es afirmaciones de verdad, afirmaciones de hecho como axiomas matemáticos. Te dice algo. El conocimiento imperativo, o de procedimiento, le dice paso a paso cómo llegar a algo. Esa es la definición de un algoritmo esencialmente. Si lo desea, compare un lenguaje de programación con el idioma inglés. Las oraciones declarativas dicen algo. Un ejemplo aburrido, pero aquí hay una manera 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 solicitud. La programación imperativa, entonces, es solo una lista de comandos (haz esto, haz eso). Esta es 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 programación declarativa hace lo mismo.
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 diferencia tiene que ver principalmente con el nivel general de abstracción. Con la declaración, en algún momento, está tan lejos de los pasos individuales que el programa tiene mucha libertad con respecto a cómo obtener su resultado.
Podrías ver que cada pieza de instrucción cae en algún lugar en un continuo:
Grado de abstracción:
Declarative <<=====|==================>> Imperative
Ejemplo del mundo real declarativo:
- Bibliotecario, por favor revíseme una copia de Moby Dick. (El bibliotecario, a su discreción, elige el mejor método para realizar la solicitud)
Ejemplo imperativo del mundo real:
- Ir a la biblioteca
- Encuentra el sistema de organización de libros (Catálogo de tarjetas - Old school)
- Investigue cómo usar los catálogos de tarjetas (también lo olvidó, a la derecha)
- Averigua cómo están etiquetados y organizados los estantes.
- Averigua cómo se organizan los libros en un estante.
- Referencia cruzada de la ubicación del libro del catálogo de tarjetas con el sistema de organización para encontrar dicho libro.
- Lleve el libro al sistema de check-out.
- Mira el libro
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 gustó una explicación de un curso de Cambridge + sus ejemplos:
- Declarativo : especifique qué hacer, no cómo hacerlo
- Por ejemplo: HTML describe lo que debe aparecer en una página web, no cómo debe dibujarse en la pantalla
- Imperativo - especifique qué y cómo
-
int x;
- que (declarativo) -
x=x+1;
- cómo
-
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).
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 IU dibujada con estos Constructores es declarativa por naturaleza, donde arrastramos y soltamos los componentes. El diseño real ocurre por debajo y realizado por el marco y el sistema.
Pero también podemos dibujar todos los componentes en código, y eso es imperativo en la naturaleza.
Además, algunos idiomas nuevos como Angular JS se centran en el diseño declarativo de IU y es posible que veamos muchos otros idiomas que ofrecen el mismo soporte. Al igual que JAVA, no tiene ninguna buena forma declarativa de dibujar aplicaciones de escritorio nativas en JAVA swing o JAVA FX, pero en un futuro próximo podrían hacerlo.
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:
- Crear una colección de resultados.
- Paso a través de cada número en la colección
- 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.
programa declarativo es solo un dato para su implementación imperativa más o menos "universal" / vm.
ventajas: 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 algún formato DSL. Lo mejor y la frecuencia utilizada en las estructuras de datos de DSL son los conjuntos y las tablas. Porque no tienes dependencias entre elementos / filas. y cuando no tiene dependencias, tiene libertad para modificar y facilidad de soporte. (compare, por ejemplo, módulos con clases: con módulos que le gustan y con clases que tiene un problema de clase base frágil) todos los bienes de declaratividad y DSL se derivan 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 implementación paralela, por ejemplo. o transfiéralas a otros sistemas operativos, etc. Todas las interfaces o protocolos de aislamiento modular que sean buenos se ofrecen con tanta libertad y facilidad de soporte.
Desventajas: adivinas bien. La implementación del algoritmo / vm imperativo genérico (y parametrizado por DSL) puede ser más lenta y / o con menos memoria que una específica. en algunos casos. Si esos casos son raros, simplemente olvídalo, deja 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 ...
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 el haskell de Jack-of-all-trades - está a medio camino entre el ML simple fuerte y el Prolog flexible de metaprog y ... qué monstruo es. puede ver Prolog como un Haskell con funciones / predicados solo booleanos. y lo simple que es su flexibilidad contra Haskell ...
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.