informatica:programacion:cursos:programacion_avanzada_javascript:lambdas
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Próxima revisión | Revisión previa | ||
| informatica:programacion:cursos:programacion_avanzada_javascript:lambdas [2024/10/15 12:28] – creado tempwin | informatica:programacion:cursos:programacion_avanzada_javascript:lambdas [2024/10/30 12:49] (actual) – [La pérdida de this (II)] tempwin | ||
|---|---|---|---|
| Línea 55: | Línea 55: | ||
| Las siguientes dos imágenes muestran las diferencias entre ambos entornos: | Las siguientes dos imágenes muestran las diferencias entre ambos entornos: | ||
| - | <WRAP center round todo 60%> | + | {{ : |
| - | Comportamiento en FF | + | |
| - | </ | + | |
| - | <WRAP center round todo 60%> | + | {{ : |
| - | Comportamiento en NodeJs | + | |
| - | </ | + | |
| ==== Sintaxis " | ==== Sintaxis " | ||
| Línea 75: | Línea 71: | ||
| ===== El operador flecha (arrow, fat arrow) ===== | ===== El operador flecha (arrow, fat arrow) ===== | ||
| - | Este operador introduce una sintaxis nueva, más sencilla para declarar funciones anónimas. Observa las diferencias: | + | Este operador introduce |
| + | <code javascript> | ||
| let foo = function() {return 42}; // Sintaxis tradicional | let foo = function() {return 42}; // Sintaxis tradicional | ||
| let foo = () => 42; // Usando el operador flecha | let foo = () => 42; // Usando el operador flecha | ||
| + | </ | ||
| Indudablemente la segunda sintaxis es mucho más clara, sencilla y concisa. Veamos un poco cómo usarla en más escenarios. | Indudablemente la segunda sintaxis es mucho más clara, sencilla y concisa. Veamos un poco cómo usarla en más escenarios. | ||
| - | Funciones que solo devuelven una expresión | ||
| - | Este es el escenario óptimo para el operador flecha. La sintaxis es muy sencilla cuando la función básicamente consiste en un return. Es el escenario | + | ==== Funciones |
| + | Este es el escenario óptimo para el operador flecha. La sintaxis es muy sencilla cuando la función básicamente consiste en un '' | ||
| + | |||
| + | <code javascript> | ||
| let foo = () => 42; // Sin argumentos. Se debe usar paréntesis vacíos como argumentos. No se usa return. | let foo = () => 42; // Sin argumentos. Se debe usar paréntesis vacíos como argumentos. No se usa return. | ||
| let foo2 = x => x + 42; // Con un argumento. No se usa return. | let foo2 = x => x + 42; // Con un argumento. No se usa return. | ||
| let foo3 = (x) => x + 42; // Idéntico al caso anterior. Los paréntesis en el argumento son opcionales. No se usa return. | let foo3 = (x) => x + 42; // Idéntico al caso anterior. Los paréntesis en el argumento son opcionales. No se usa return. | ||
| let sum = (x,y) => x + y; // Con más de un argumento. Los paréntesis en los argumentos son obligatorios. No se usa return. | let sum = (x,y) => x + y; // Con más de un argumento. Los paréntesis en los argumentos son obligatorios. No se usa return. | ||
| + | </ | ||
| - | En este caso la función foo no acepta parámetros y devuelve siempre el valor 42. Las funciones foo2 y foo3 son idénticas: aceptan un parámetro y devuelven el valor del parámetro sumándole 42, mientras que la función sum suma los dos parámetros que se le pasan y devuelve el valor. | + | En este caso la función |
| - | Veamos cómo realmente el uso del operador flecha mejora la legibilidad en ciertos escenarios. | + | Veamos cómo realmente el uso del **operador flecha mejora la legibilidad** en ciertos escenarios. |
| - | ej. Array.prototype tiene una función llamada filter que filtra los elementos de un array que cumplan un cierto predicado. Este predicado es una función que se pasa como parámetro a filter, que es invocada por cada elemento y que debe devolver true si el elemento cumple el filtro. Así podríamos obtener los elementos pares de un array simplemente con: | + | '' |
| - | | + | <code javascript> |
| + | [1, | ||
| + | </ | ||
| - | Este código devuelve el array [2,4] (es decir los elementos que cumplen el filtro). Pues bien, el mismo código escrito usando el operador flecha es el siguiente: | + | Este código devuelve el array '' |
| + | <code javascript> | ||
| [1, | [1, | ||
| + | </ | ||
| Se puede ver que el segundo código es mucho más conciso y fácil de leer que el primero. En este escenario el uso del operador flecha supone una indudable mejora respecto a la sintaxis tradicional. | Se puede ver que el segundo código es mucho más conciso y fácil de leer que el primero. En este escenario el uso del operador flecha supone una indudable mejora respecto a la sintaxis tradicional. | ||
| - | Cuando la función devuelve un objeto usando object notation entonces debemos envolver el valor de retorno entre paréntesis. Esto es para no confundir al parser: | + | Cuando la función devuelve un objeto usando |
| + | <code javascript> | ||
| let foo = () => {a:30, b: 40}; // Error de sintaxis | let foo = () => {a:30, b: 40}; // Error de sintaxis | ||
| let foo = () => ({a:30, b: 40}); // OK | let foo = () => ({a:30, b: 40}); // OK | ||
| + | </ | ||
| + | |||
| + | La razón de esta confusión del //parser// tiene que ver con el siguiente escenario del operador flecha: funciones que tienen más de una sentencia. | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | **parser**: Analizador sintáctico de código | ||
| + | </ | ||
| - | La razón de esta confusión del parser tiene que ver con el siguiente escenario del operador flecha: funciones que tienen más de una sentencia. | + | ==== Funciones con varias sentencias |
| - | Funciones con varias sentencias | + | |
| El operador flecha puede usarse para definir funciones con varias sentencias. En este caso sus ventajas no son tan evidentes (aunque siguen existiendo). Si tenemos un código como el siguiente: | El operador flecha puede usarse para definir funciones con varias sentencias. En este caso sus ventajas no son tan evidentes (aunque siguen existiendo). Si tenemos un código como el siguiente: | ||
| + | <code javascript> | ||
| let foo = function() { | let foo = function() { | ||
| console.log(' | console.log(' | ||
| return 42; | return 42; | ||
| - | }; | + | }; |
| + | </ | ||
| Podemos convertirlo usando el operador flecha para que quede de la siguiente manera: | Podemos convertirlo usando el operador flecha para que quede de la siguiente manera: | ||
| + | <code javascript> | ||
| let foo = () => { | let foo = () => { | ||
| console.log(' | console.log(' | ||
| return 42; | return 42; | ||
| }; | }; | ||
| + | </ | ||
| - | Se puede observar en este caso como después del operador flecha se abren llaves. Estas llaves es lo que indica que la función tiene más de una sentencia. Observa también como ahora es necesario el uso de return. | + | Se puede observar en este caso como **después del operador flecha se abren llaves**. Estas llaves es lo que indica que la función tiene más de una sentencia. Observa también como ahora **es necesario el uso de '' |
| En este caso, en lo que respecta a la legibilidad no hay muchas diferencias entre usar el operador flecha o una declaración de función anónima tradicional (posteriormente veremos otra ventaja de usar el operador flecha, incluso en este caso). | En este caso, en lo que respecta a la legibilidad no hay muchas diferencias entre usar el operador flecha o una declaración de función anónima tradicional (posteriormente veremos otra ventaja de usar el operador flecha, incluso en este caso). | ||
| - | El hecho de que "abrir llave" después del operador flecha indique que empieza una serie de sentencias para la función es lo que hace que debamos usar paréntesis si usamos el operador flecha para definir funciones que tan solo devuelven un objeto en object notation (JSON). | + | El hecho de que "abrir llave" después del operador flecha indique que empieza una serie de sentencias para la función es lo que hace que debamos usar paréntesis si usamos el operador flecha para definir funciones que tan solo devuelven un objeto en //object notation// (JSON). |
| Esto es porque el siguiente código: | Esto es porque el siguiente código: | ||
| + | <code javascript> | ||
| let foo = () => {a:20, b:30}; | let foo = () => {a:20, b:30}; | ||
| + | </ | ||
| El motor de JavaScript lo interpreta como: | El motor de JavaScript lo interpreta como: | ||
| + | <code javascript> | ||
| let foo = function() { | let foo = function() { | ||
| a:20, b:30 | a:20, b:30 | ||
| }; | }; | ||
| + | </ | ||
| Lo que se puede observar es un error de sintaxis clarísimo. El usar paréntesis evita esta ambigüedad, | Lo que se puede observar es un error de sintaxis clarísimo. El usar paréntesis evita esta ambigüedad, | ||
| + | <code javascript> | ||
| let foo = () => ({a:20, b:30}); | let foo = () => ({a:20, b:30}); | ||
| + | </ | ||
| Es interpretado por el motor de JavaScript como: | Es interpretado por el motor de JavaScript como: | ||
| + | <code javascript> | ||
| let foo = function() { | let foo = function() { | ||
| return {a:20, b:30}; | return {a:20, b:30}; | ||
| }; | }; | ||
| + | </ | ||
| Que es precisamente, | Que es precisamente, | ||
| - | ===== ===== | + | ===== DEMO: Sintaxis y uso del operador flecha |
| - | ===== ===== | + | Tradicionalmente, |
| - | ===== ===== | + | <code javascript> |
| + | var a = function(i) { | ||
| + | return i % 2 == 0; | ||
| + | } | ||
| + | </ | ||
| - | ===== ===== | + | El **operador " |
| - | ===== ===== | + | <code javascript> |
| + | var a = (i) => i % 2 == 0; | ||
| + | // Sería válido también esto por haber solo un parámetro en la función: | ||
| + | // var a = i => i % 2 == 0; | ||
| + | } | ||
| + | </ | ||
| - | ===== ===== | + | Veamos ahora un uso real de este nuevo operador y cómo nos ayuda a simplificar la sintaxis. Sintaxis clásica: |
| + | <code javascript> | ||
| + | // Multiplicaremos los elementos del array por 2 | ||
| + | var resultado = [1, 2, 3].map(function(e) { | ||
| + | return e * 2; | ||
| + | }) | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | '' | ||
| + | </ | ||
| + | |||
| + | Usando el operador flecha: | ||
| + | |||
| + | <code javascript> | ||
| + | var resultado = [1, 2, 3].map(e => e * 2); | ||
| + | </ | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | Vemos que en funciones que esperan como parámetro una función, la sintaxis flecha nos ahorra escritura y además se hace más fácil de leer. | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== La " | ||
| + | |||
| + | El valor que tiene '' | ||
| + | |||
| + | Esta casuística se da cuando se observa que el valor de '' | ||
| + | |||
| + | <code javascript> | ||
| + | var obj = { | ||
| + | values: [4, 8, 15, 16, 23, 42], | ||
| + | filter: function(v) { return v % 2 == 0 || v == 23}, | ||
| + | getValues: function() { return this.values}, | ||
| + | getFilteredValues: | ||
| + | return this.values.filter(function(v) { | ||
| + | return this.filter(v); | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | El siguiente código define un objeto '' | ||
| + | |||
| + | Tómate un tiempo para pensarlo, si quieres. La solución está en el siguiente apartado. | ||
| + | |||
| + | ===== La pérdida de this (II) ===== | ||
| + | |||
| + | El error que nos da el código anterior es el siguiente (como siempre, el mensaje exacto puede variar según el entorno de JavaScript que uses): | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | El error lo que nos dice es que '' | ||
| + | |||
| + | La razón principal del error es que **el valor de '' | ||
| + | |||
| + | El siguiente diagrama muestra el valor de '' | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | Lo importante es tener presente que dentro de la función anónima que se pasa como parámetro a la llamada a '' | ||
| + | |||
| + | ==== Solucionando la pérdida de this ==== | ||
| + | |||
| + | Existen dos mecanismos para solucionar la pérdida de '' | ||
| + | |||
| + | El primero consiste en **declarar una variable y asignarla a '' | ||
| + | |||
| + | Por convención a esta variable se la suele llamar '' | ||
| + | |||
| + | <code javascript> | ||
| + | var obj = { | ||
| + | values: [4, 8, 15, 16, 23, 42], | ||
| + | filter: function(v) { return v % 2 == 0 || v == 23}, | ||
| + | getValues: function() { return this.values}, | ||
| + | getFilteredValues: | ||
| + | var self = this; | ||
| + | return this.values.filter(function(v) { | ||
| + | return self.filter(v); | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | La segunda técnica que se suele utilizar para evitar la pérdida de '' | ||
| + | |||
| + | <code javascript> | ||
| + | var obj = { | ||
| + | values: [4, 8, 15, 16, 23, 42], | ||
| + | filter: function(v) { return v % 2 == 0 || v == 23}, | ||
| + | getValues: function() { return this.values}, | ||
| + | getFilteredValues: | ||
| + | return this.values.filter(function(v) { | ||
| + | return this.filter(v); | ||
| + | }.bind(this)); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Observa cómo se aplica '' | ||
| + | |||
| + | ===== DEMO: call, bind y apply ===== | ||
| + | |||
| + | Ejemplos para modificar el valor de '' | ||
| + | |||
| + | Si tenemos la siguiente función: | ||
| + | |||
| + | <code javascript> | ||
| + | function foo(i) { | ||
| + | this.una_propiedad = i; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Y la ejecutamos: | ||
| + | |||
| + | <code javascript> | ||
| + | foo(10); | ||
| + | |||
| + | console.log(" | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | <code javascript> | ||
| + | var foo = new foo(10); | ||
| + | |||
| + | console.log(" | ||
| + | </ | ||
| + | |||
| + | Usando '' | ||
| + | |||
| + | <code javascript> | ||
| + | var a = {p: 10}; | ||
| + | </ | ||
| + | |||
| + | Lo probamos: | ||
| + | |||
| + | <code javascript> | ||
| + | foo.call(a, 10); // -> Object {p: 10, una_propiedad: | ||
| + | </ | ||
| + | |||
| + | Con '' | ||
| + | |||
| + | <code javascript> | ||
| + | foo.apply(a, | ||
| + | </ | ||
| + | |||
| + | Otro método es usar '' | ||
| + | |||
| + | <code javascript> | ||
| + | var f = foo.bind(a); | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | <code javascript> | ||
| + | f(200); | ||
| + | |||
| + | a; // -> Object {p: 10, una_propiedad: | ||
| + | </ | ||
| + | |||
| + | ===== this y funciones definidas con el operador flecha ===== | ||
| + | |||
| + | Otra de las ventajas de usar el operador flecha para definir funciones, **es que las funciones definidas con éste capturan el valor de '' | ||
| + | |||
| + | Observa cómo queda el código anterior usando una función definida con el operador flecha: | ||
| + | |||
| + | <code javascript> | ||
| + | var obj = { | ||
| + | values: [4, 8, 15, 16, 23, 42], | ||
| + | filter: function(v) { return v % 2 == 0 || v == 23}, | ||
| + | getValues: function() { return this.values}, | ||
| + | getFilteredValues: | ||
| + | return this.values.filter(v => this.filter(v) ); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | El código funciona correctamente, | ||
| + | |||
| + | Solo por esto ya tenemos una ventaja clara de usar el operador flecha. | ||
| + | |||
| + | ==== Operador flecha y funciones de primer nivel ==== | ||
| + | |||
| + | Supón el siguiente código, que usa el operador flecha para definir una función de un objeto: | ||
| + | |||
| + | <code javascript> | ||
| + | var obj={ | ||
| + | nick: ' | ||
| + | getUrl: () => ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | La pregunta es ¿cuál es el resultado de la función '' | ||
| + | |||
| + | Si has respondido '' | ||
| + | |||
| + | La función '' | ||
| + | |||
| + | <code javascript> | ||
| + | var obj={ | ||
| + | nick: ' | ||
| + | getUrl: function() { return ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ¿Por qué la función declarada con el operador flecha no funciona y la función declarada a la manera tradicional sí? ¿No se supone que básicamente el operador flecha es un sintaxis más cómoda para declarar funciones? | ||
| + | |||
| + | Sí, es cierto que el operador flecha es una sintaxis más cómoda para declarar funciones, pero recuerda que, tal y como hemos visto antes, **las funciones declaradas con el operador flecha capturan el valor de '' | ||
| + | |||
| + | <code javascript> | ||
| + | var test = { | ||
| + | nick: ' | ||
| + | url: ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | El valor de '' | ||
| + | |||
| + | Ahora bien, cuando usas el operador flecha para definir la función estás capturando el valor de '' | ||
| + | |||
| + | <code javascript> | ||
| + | var obj={ | ||
| + | nick: ' | ||
| + | getNick: function() { return ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | En esta versión usamos '' | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | En resumen: **no uses el operador flecha para definir las propias funciones de un objeto. Úsalo para definir aquellas funciones anónimas que pasas como parámetros a otras funciones**. | ||
| + | </ | ||
| + | |||
| + | ==== El operador flecha y bind ==== | ||
| + | |||
| + | Se ha visto como el operador flecha captura el valor de '' | ||
| + | |||
| + | <code javascript> | ||
| + | var demo = (() => this.nick).bind({nick: | ||
| + | var nick = demo(); | ||
| + | </ | ||
| + | |||
| + | En este código definimos una función con el operador flecha y usamos '' | ||
| + | |||
| + | Pero la realidad es que el valor de '' | ||
| + | |||
| + | Eso mismo ocurre si usas '' | ||
| + | |||
| + | <code javascript> | ||
| + | var demo = function() { return this.nick}.bind({nick:' | ||
| + | var demo2 = demo.bind({nick:' | ||
| + | var nick = demo2(); // eiximenis | ||
| + | </ | ||
| + | |||
| + | ===== DEMO: La propagación de this en el operador flecha ===== | ||
| + | |||
| + | Consideremos el siguiente objeto: | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | } | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | stuff; // -> Object {mult: 2, data: Array[4], log: stuff.log() } | ||
| + | |||
| + | stuff.log(); | ||
| + | </ | ||
| + | |||
| + | Ahora crearemos una función que devolverá un array con la multiplicación de los elementos del array '' | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | }, | ||
| + | multData: function() { | ||
| + | return this.data.map(function(e) { | ||
| + | return e * this.mult; | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Ejecutamos: | ||
| + | |||
| + | <code javascript> | ||
| + | stuff.mult = 10; | ||
| + | |||
| + | var md = stuff.multData(); | ||
| + | |||
| + | md; // -> Array[NaN, NaN, NaN, NaN] | ||
| + | </ | ||
| + | |||
| + | Esto pasa porque en el '' | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | }, | ||
| + | multData: function() { | ||
| + | return this.data.map(function(e) { | ||
| + | console.log(this); | ||
| + | return e * this.mult; | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | // Ejecutamos: | ||
| + | stuff.multData(); | ||
| + | </ | ||
| + | |||
| + | Esto es lo que se conoce como **pérdida de '' | ||
| + | |||
| + | Una de las soluciones es buscar dónde tiene '' | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | }, | ||
| + | multData: function() { | ||
| + | var self = this; | ||
| + | return this.data.map(function(e) { | ||
| + | return e * self.mult; | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | // Ejecutamos | ||
| + | stuff.multData(); | ||
| + | </ | ||
| + | |||
| + | Otra forma es utilizando la función '' | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | }, | ||
| + | multData: function() { | ||
| + | return this.data.map(function(e) { | ||
| + | return e * this.mult; | ||
| + | }.bind(this)); | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | // Ejecutamos | ||
| + | stuff.multData(); | ||
| + | </ | ||
| + | |||
| + | Las funciones definidas con el operador flecha también pueden ser usadas para esto: | ||
| + | |||
| + | <code javascript> | ||
| + | var stuff = { | ||
| + | mult: 2, | ||
| + | data: [1, 2, 3, 4], | ||
| + | log: function() { | ||
| + | console.log(" | ||
| + | }, | ||
| + | multData: function() { | ||
| + | return this.data.map(e => e * this.mult); | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | // Ejecutamos | ||
| + | stuff.multData(); | ||
| + | </ | ||
| ===== Funciones lambda ===== | ===== Funciones lambda ===== | ||
| + | |||
| + | Hasta ahora se ha usado la expresión " | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Esta sección es puramente informativa y se incluye por completitud. El cálculo lambda es un sistema formal que permite definir el concepto de " | ||
| + | </ | ||
| + | |||
| + | ==== Computabilidad ==== | ||
| + | |||
| + | El cálculo lambda es un sistema formal que se usa para verificar la computabilidad, | ||
| + | |||
| + | Lo importante sobre la máquina de Turing en nuestro contexto no es cómo funciona, sino el hecho de que **computacionalmente una máquina de Turing es equivalente al ordenador más potente que podamos construir hoy en día**. Incluso los posiblemente futuros ordenadores cuánticos son equivalentes computacionalmente a una máquina de Turing. Ten presente que " | ||
| + | |||
| + | Puede parecer que cualquier posible problema va a poder ser resuelto, con un tiempo arbitrario (y un consumo arbitrario de ciertos recursos, tales como cinta en una máquina de Turing o memoria en un ordenador actual). Pero la realidad es que esto no es así y **por raro que pueda parecer existen problemas que no pueden ser resueltos con ningún algoritmo, incluso contando con tiempo y recursos ilimitados**. Detectar qué problemas son esos es uno de los objetivos de la teoría de la computabilidad. | ||
| + | |||
| + | ==== El problema de la parada ==== | ||
| + | |||
| + | El problema de la parada es, probablemente, | ||
| + | |||
| + | Su definición es muy simple: dado un programa (a ejecutar por una máquina de Turing, o un ordenador) y su entrada inicial, se trata de decidir si dicho programa (con la entrada suministrada) terminará su ejecución en algún momento o por el contrario estará ejecutándose eternamente (p. ej. en un bucle infinito). El propio Turing demostró que este problema es no computable, es decir, es imposible crear algoritmo alguno que pueda resolverlo. | ||
| + | |||
| + | ==== Cálculo lambda ==== | ||
| + | |||
| + | El cálculo lambda es una herramienta que permite decidir la computabilidad o no de una función determinada. No entraremos aquí en el cómo (echa un vistazo a la [[https:// | ||
| + | |||
| + | Imagina dos funciones. La primera, llamada " | ||
| + | |||
| + | * Identidad: '' | ||
| + | * Suma: '' | ||
| + | |||
| + | El cálculo lambda realiza algunas consideraciones sobre esas funciones. La primera es que **las funciones no necesitan ser explícitamente nombradas**. Así la función " | ||
| + | |||
| + | Otra consideración es que el nombre de los parámetros no tiene importancia alguna. Así las funciones '' | ||
| + | |||
| + | Una tercera consideración interesante es que **toda función que tenga dos parámetros y devuelva un valor puede ser reescrita como una función que tenga un solo parámetro, pero que devuelva otra función, que acepta un parámetro y devuelve un valor**. Este proceso se llama **currificación** y es una de las bases de la programación funcional (por cierto, ¡es posible implementar currificación en JavaScript!). | ||
| + | |||
| + | En el cálculo lambda, las funciones se definen mediante " | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Observa como la notación del operador flecha es casi calcada a la notación de las funciones anónimas (no así a la notación de las propias " | ||
| + | </ | ||
| + | |||
| + | No vamos a contar más cosas sobre el cálculo lambda (ahora ya entraríamos en un territorio mucho más complejo). Tan solo comentar que como sistema formal tiene exactamente la misma potencia computacional que una máquina de Turing, es decir, cualquier algoritmo calculable por una máquina de Turing (lo que significa decir cualquier algoritmo posible) es representable en cálculo lambda. | ||
| + | |||
| + | La importancia del cálculo lambda en el desarrollo de la informática como ciencia es capital (de hecho se podría considerar el cálculo lambda como un (el primer) lenguaje de programación). El cálculo lambda ejerce una gran influencia, especialmente en el desarrollo de lenguajes funcionales tales como LISP o Haskell. | ||
| + | |||
| + | Simplemente quería que supieses de dónde proviene el hecho de que muchos desarrolladores llamemos a las funciones declaradas con el operador flecha, funciones o expresiones lambda. | ||
informatica/programacion/cursos/programacion_avanzada_javascript/lambdas.1728988137.txt.gz · Última modificación: por tempwin
