Como sabemos, las estructuras de control son las encargadas de representar cierta inteligencia para tomar decisiones por parte de un algoritmo. Este es el principal aporte que realiza el lenguaje Dynamo para potenciar el alcance del compilador de Lit. Las tres estructuras de control que maneja Dynamo son tres: Condicionales, Bucles y Rangos. A continuación abordaremos las particularidades y utilización de cada una de ellas.
Es importante recordar que todos los ejemplos que verás a continuación, corresponden a la versión actual de Lit y Dynamo que es Alfa 0.0.1. Ten presente que al tratarse de un primer prototipo funcional, las estructuras pueden cambiar sensiblemente en el futuro cercano.
Las Declaraciones de bloque y Flujo de bloque son una serie de caracteres especiales que le indican al compilador de Dynamo que lo que se encuentra dentro de los mismos son instrucciones de código para ser evaluadas.
Antes de pasar a analizar como trabajar con las estructuras de control de Dynamo, creemos que es interesante explicar algunos conceptos que están en la base conceptual de las mismas y, en general, del desarrollo de todo el lenguaje:
1.- Tal como se puede ver en la sección dedicada a los Templates, los mismos pueden contener fragmentos o partes de código HTML que no se desea mezclado con instrucciones de Dynamo. Y dentro de estos fragmentos pueden existir secuencias de caracteres como por ejemplo {}, (), >, u otros que sean similares a la sintaxis utilizada para declarar las Estructuras de control de Dynamo. Esto no es un problema para el compilador, ya que es lo suficientemente inteligente para detectar cuando debe ajecutarse y cuando se encuentra frente a una colisión fortuita de algunos caracteres.
2.- Los bloques de código escritos en Dynamo pueden encontrarse tanto en un Template base, así como en cualquier componente o fragmento importado. Esto incluye aquellos que puedar ser compaginados desde un sitio externos, siempre que cuente con los autorización necesaria.
3.- El compilador de Dynamo integrado en LitGirl fue desarrollado desde un enfoque "A prueba de errores". Intentará deducir qué intentas hacer y solucionar todas las inconsistencias posibles. El compilador en ningún caso retorna datos de error al usuario. Además, Dynamo cuenta en su sintaxis con una sentencia de escape para, justamente, escapar de cualquier situación imprevista o que no ha sido capaz de solucionar. Recomendamos enfáticamente su uso. Esto evita, por poner un ejemplo, que el usuario vea en una aplicación algo parecido a esto: Hola {name}. Bastante típico cuando se utilizan motores de plantillas, programación embebida o el usuario aplica algunos tipos de traductores en tiempo real.
4.- La seguridad es una preocupación constante y realmente reclama toda nuestra atención. Sabemos que no existe absolutamente ningún sistema o lenguaje totalmente invulnerable, además de tener que contar con el factor del error humano. Por ello, hemos prestado especial cuidado en hacer que el compilador de Dynamo sea lo bastane cauteloso como para no permitir la inyección de instrucciones potencialmente peligrosas.
5.- Uno de los lineamientos principles que seguimos en el desarrollo de Dynamo es el hacer que sus declaraciones sean lo más compactas posible. Muchas palabras clave que son instrucciones y pistas para el compilador, no las encontraran en Dynamo. En consecuencia, nuestro mayor esfuerzo se dedica a dotar de mayor "inteligencia" al propio compilador, para que sea capaz de saber por sí mismo si debe evaluar una condición, ejecutar un rango, continuar, detenerse, etc. Por otro lado, para facilitar la escritura de código, muchas de las palabras claves se han sustituido por secuencias de uno o dos símbolos.
Las declaraciones de bloque se componen de una "etiqueta" de apertura y una "etiqueta" de cierre. El compilador de Dynamo solo se enfocará en lo que se encuentre dentro de las mismas e ignorará lo demás. De momento, por simplicidad, Dynamo no cuenta con comentarios propios. Si necesitas dejar comentarios en el código para el futuro o para guía de tu equipo, puedes hacerlo fuera de las Estructuras de bloque usando los comentarios HTML normales. Quizas, agregando alguna convención para distinguir a simple vista que hace referencia a Dynamo.
1.- {>> Etiqueta de apertura para una Declaración de bloque.
2.- >>} Etiqueta de cierre para una Declaración de bloque.
Para entender mejor como declarar la apertura y cierre de bloques, mira el siguiente ejemplo:
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><!-- [Dyn]: Esto es un posible ejemplo de comentario [/Dyn] -->{{>>//Código Dynamo>>}}<section><div><!-- Este contenido HTML se mantiene inalterado --></div><ul>{{>>//Código Dynamo>>}}</ul></section></body></html>
Los condicionales en Dynamo (al igual que en todos los lenguajes de programación), permiten que nuestro código tome decisiones en base a si una o más condiciones se cumplen. En la versión actual de Dynamo, la estructura condicional que ofrece es una interpretaón propia del tradicional if - else. A continuación veremos algunos ejemplos de la sintaxis y la forma de agregar condicionales de Dynamo en los templates de LitGirl.
Su funcionamiento es el habitual en la mayoría de lenguajes, en ese aspecto no hay mucho que agregar. La peculiaridad de los condicionales en Dynamo, está dada por la forma en que estos se declaran. Precisamente, en entender su sintaxis es en lo que nos enfocaremos en los ejemplos a continuación.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><!-- [Dyn]: Esto es un posible ejemplo de comentario [/Dyn] --><h1>{>> (data.register.user === user)$> Hola [[user]] de nuevo. >> out$> Hola [[data.sayDefault]].>>}</h1><section><div><!-- Este contenido HTML se mantiene inalterado --></div><ul>{{>>//Código Dynamo>>}}</ul></section></body></html>
Esta es la sintaxis de una sentencia If - Else simple utilizando Dynamo. Veamos ahora cada uno de sus componentes (obviaremos la apertura y cierre del bloque que ya vimos en un apartado anterior):
1.- (data.register.user === user) Dentro de los paréntesis expresa una condición de igualdad estricta a evaluar. Similar a como se declara en otros lenguajes. Te recomendamos ver la sección de Operadores admitidos, para tener una idea más clara sobre el tipo de condiciones que puedes declarar.
2.- $> Indica la salida del programa si la condición se ha cumplido.
3.- Hola [[user]] de nuevo. En el supuesto de que la condición se haya cumplido, esto será lo que se evaluará a continuación, antes de imprimirse por pantalla.
4.- [[user]] ¡Lo has adivinado! Esta estructura es para la asignación dinámica de datos. Tomará el valor de la variable user, en este caso, si la condición se ha cumplido. Aunque, también podría ser cualquier otro dato almaenado que necesitaras. * Lo que debes tener presente es que siempre debe tratarse de una referencia a un dato existente. Por ejemplo: una variable, una constante, propiedad de un objeto, etc.
5.- >> En caso de que la condició no se cumpla, le indica al programa que pase a la siguiente instrucción.
6.- out Esta es la variante de un else en Dynamo. Aunque, en realidad, no es solamente eso. Tal como su nombre literal lo dice, significa "afuera". En una sección anterior de esta página mencionamos cómo Dynamo maneja los errores. Pues bien, este es el punto de acceso de los usuarios al Manejador de errores del compilador. Permite que en caso de que no se cumpla la condición, o lo anterior falle, fuerce una salida antes de cerrar el proceso y liberar los recursos. En este caso, hemos insertado dentro del mensaje, a efectos didácticos, una referencia a un saludo por defecto. Sin embargo, la recomendación es utilizar un texto literal para mayor seguridad. *Si bien su uso no es obligatorio, lo sugerimos.
Si bien el uso de los () es admitido, no es algo requerido. Como ya hemos mencionado, la idea detrás de Dynamo es hacer lo más posible con lo mínimo posible. En el ejemplo anterior los hemos utilizado para mejorar la legibilidad y no por otra razón. Sin ellos el código continuaría funcionando como se espera.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><aside class="sidebar"><ul><!-- [Dyn]: Ejemplo de múltiples if-else consecutivos [/Dyn] -->{>> (storage.user)$> <li>Menu [[storage.user]]</li> >> out$> <li>Menu</li>>>}{>> (storage.user && storage.menu)$> <li>[[storage.menu.0]]</li><li>[[storage.menu.1]]</li> >> out$> <li>No tienes preferencias</li>>>}</ul></aside><section><div><!-- Este contenido HTML se mantiene inalterado --></div></section></body></html>
Como puedes observar, declarar varios If - Else consecutivos que4 deben ser todos evaluados, es tan sencillo como aislar cada uno en su propia Estructura de bloque.
Como puedes observar en la salida del segundo condicional, existen dos referencia parecidas a esta storage.menu.X. Esto le indica a Dynamo que en el objeto storage existe una propiedad menu (la cual es un array), y que debe obtener el valor del indice indicado por el número luego del último punto. Al contrario de lo que es habitual en muchos lenguajes donde el índice se debe pasar dentro de corchetes [], en Dynamo no es necesario, se pasa como si fuera una propiedad.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><div><!-- Este contenido HTML se mantiene inalterado --></div><section><p>{>> (document.referrer === "http://domain.com/")$> <strong>Has accedido desde: http://domain.com/</strong>. >>(!document.referrer && user !== localStorage.getItem('user'))$> <strong>No sabemos de dónde vienes ni quién eres.</strong> >>out$> Gracias por visitarnos.>>}</p></section></body></html>
Este tercer ejemplo de condicionales que puedes observar dentro de las etiquetas HTML <footer> y </footer>es la forma en que se declaran las estructuras de tipo If - Else If - Else utilizando Dynamo.
El uso de Variables de transpilación y de Constantes de compaginación dentro de condicionales, bucles y rangos no es totalmente estable. Si bien, lo serán en próximas versiones del compilador, de momento, desaconsejamos su uso en los contextos mencionados.
Si has prestado atención al último ejemplo, habrás notado que dentro de algunos condiconales accedemos a API's JavaScript del Navegador como son: localStorage y document.referrer. Si bien, aún está en etapa de evaluación su comportamiento, Dynamo ya cuenta con esta capacidad integrada en su especificación. Te recomendamos ver la sección de API's Admitidas para mayor información.
* De momento el acceso a las mismas está pensado para que sea en modo solo lectura. Aunque ténicamente en algunos casos el acceso de escritura funcionaría, no forma parte de las especificaciones de esta versión.
Los Bucles y Rangos son las dos estructuras más poderosas que ofrece Dynamo de momento. El concepto subyacente tras ellas es el mismo que se encuentra en estructuras similares de otros lenguajes: realizar iteraciones recursivas sobre objetos iterables por un número determinado de veces. Sin embargo, Dynamo lleva esto a un nivel que permite realizar tareas más complejas.
En Dynamo, estas estructuras son una combinación de los bucles básicos (for, while, do-while) que podemos encontrar en lenguajes como JavaScript, PHP, etc, con otros tipos. Por ejemplo, los bucles for..of, for..in (también de JavaScript), los range de Phyton, el foreach al estilo de PHP, entre algunos otros. Con la particularidad de que todos pertenecen a una misma denominación en Dynamo. Los llamamos: role.
Sin dudas, visto tan superficialmente, este concepto te puede resultar confuso incluso si tienes conocimientos de programación. Para ayudarte a que puedas entender mejor los ejemplos que siguen, te mencionamos sus dos pilares conceptuales prioritarios.
1.- Más con menos Este fundamento ya lo mencionamos en un apartado anterior. Se trata simplemente de lograr lo más posible con lo mínimo posible.
2.- Enfócate en lo que quieres hacer, no con qué lo pretendes hacer Desde esta perspectiva, no tiene mucho sentido tener múltiples iteradores con comportamientos diferentes. El iterador role es polimórfico, se adapta y transforma de acuerdo a los argumentos que reciba. Tú le indicas el/los dato/s que te interesa recuperar en cada iteración, y dejas a role decidir la forma más eficiente de hacerlo.
Comencemos por ver un ejemplo con dos formas diferentes de declarar las misma idea de realizar una iteración simple, pasada como parámetro a role;
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><h1>{=data.titles.iterators}</h1><aside class="sidebar"><ul><!-- [Dyn]: Ejemplo iteración simple sobre un objeto iterable con inicio numérico, sabiendo que su primer elemento tiene índice 0. [/Dyn] -->{>>role=(0 -> links)$> <li class="some-class">[[value]]</li> >>}<!-- [Dyn]: Ejemplo iteración simple sobre un objeto iterable con un caracter de asignación. Normalmente se utiliza cuando por alguna razón no se tiene certeza del valor del índice del primer elemento de un iterable. En los demás casos, automáticamente su valor inicial será asignado como 0. [/Dyn] -->{>>role=(i -> links)$> <li class="some-class">[[value]]</li> >>}</ul></aside><section><div><!-- Este contenido HTML se mantiene inalterado --></div></section><footer></footer></body></html>
Esta es la implementación más básica de role como bucle. Veamos sus partes y el significado de cada una de ellas antes de pasar a ejemplos más complejos. Obviaremos hacer referencia a las etiquetas {>> >>} sobre las que ya hablamos en el apartado Estructuras de bloque.
1.- role= Llamada y asignación de parámetros al iterador de Dynamo.
2.- (...) Al igual que lo mencionado en el apartado de Condicionales estos paréntesis de apertura y cierre son opcionales.
3.- 0 o i Posición del índice al inicio de la primera iteración. En los comentatios del código se mencionan sus particularidades.
4.- -> Este operador se puede traducir literalmente como un de. Apunta role hacia objeto que debe iterar.
5.- links El nombre del array, en este caso particular, sobre el qu realizar las iteraciones.
6.- $> Output para cada ciclo del iterador. En el apartado de Condicionales puedes encontrar mayor información sobre este operador.
7.- [[value]] Asignsción del valor obtenido en cada iteración. Ya hablamos de esta sintaxis en el apartado de Condicionales.
Ahora agregaremos un par de ejemplos para ver cómo pode filtrar iterables utilizando role.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><h1>{=data.titles.iterators}</h1><section><!-- [Dyn]: Ejemplo iteración sobre un iterable con filtrado por su índice. [/Dyn] -->{>>role=([1, 4, 7] -> images.url)$> <figure class="some-class"><img src="[[value]]" alt="" title=""></figure> >>}<!-- [Dyn]: Ejemplo iteración sobre un objeto con filtrado por sus propiedades. [/Dyn] -->{>>role=([prod1, prod4, prod7] -> images.url)$> <figure class="some-class"><img src="[[value]]" alt="" title=""></figure> >>}<div><!-- Este contenido HTML se mantiene inalterado --></div></section><footer></footer></body></html>
En este ejemplo de la aplicación del filtrado con role, la principal novedad es la aparición de una nueva estructura en la asignación de parámetros. Vamos a analizarla.
1.- [] Declaración de un arreglo como parámetro.
2.- 1, 4, 7 Índices a ser recuperados separados por comas. El orden de los iacute;ndices no es realmente relevante, aunque por convención los hemos colocado en orden ascendente. Pueden estar en cualquier combinació que se te ocurra, basta con que efectivamente existan en el objeto iterado.
3.- prod1, prod4, prod7 Similar al anterior y con las mismas reglas. La diferencia es que en este caso, evidentemente estamos iterando sobre un arreglo asociativo o un objeto literal.
Normalmente, cuando debemos combinar o emparejar datos de distintas procedencias, esto nos implica realizar acciones extra dentro de nuestros iteradores. Dynamo con role resuelve la mayor parte de estos problemas de una manera simple, como veremos en el siguiente ejemplo.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><div><!-- Este contenido HTML se mantiene inalterado --></div><!-- [Dyn]: Ejemplo iteración sobre dos objetos iterables desde su primer elemento hasta el último. [/Dyn] -->{>>role=(0 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}<!-- [Dyn]: Similar al ejemplo anterior, pero utilizando un filtrado. [/Dyn] -->{>>role=([1, 4, 7] -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}</section><footer></footer></body></html>
Estos dos ejemplos muestran la forma sencilla en que role puede emparejar datos de distintas procedencias en una sola instruccón. Teniendo en cuenta dos aspectos fundamentales:
1.- Precedencia El orden en que aparezca la asignación de valores dentro de la salida esperada, debe ser correlativo con el orden en que se declaran los objetos a iterar. Por ejmplo, si vas a asignar un [[link]] antes que una [[image]], debes declarar el objeto que contiene los links antes que el de las imágenes.
2.- Emparejamiento de tipos Puedes emparejar objetos de diferente tipo. Por ejemplo un arreglo con un objeto literal, siempre que te asegures que ambos puedan ser iterados utilizando el mismo índice. El soporte a índices individuales, puede ser agregado en el futuro, aunque de momento esto no es posible ya que causa pérdidas drásticas de rendimiento.
En aquellas situaciones en que sea necesario evaluar condiciones antes de que la iteración de role devuelva una salida, es posible agregar condicionales internos a evaluar. Lo veremos en el siguiente ejemplo.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><section><ul><!-- [Dyn]: Ejemplo de 'role' con condicionales internos [/Dyn] -->{>>role=(i -> products.prices)=>(products.prices.i < 100)$> <li class="green">[[value]]</li> >>(products.prices.i > 100 && products.prices.i < 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul><ul><!-- [Dyn]: Similar al ejemplo anterior, agregando iteración multiobjeto y filtrado** CUIDADO: ESTA FUNCIONALIDAD ESTÁ EN FASE EXPERIMENTAL ** [/Dyn] -->{>>role=([0, 2, 3, 7] -> [products.prices, breakClass])=>(products.prices.i < breakClass.i)$> <li class="green">[[value]]</li> >>(products.prices.i > breakClass.i && products.prices.i !== 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul></section></body></html>
Como puedes ver en el ejemplo, agregar condicionales dentro de role sigue las reglas de sintaxis que hemos visto para cada estructura. En este caso role actúa como envoltura para los condicionales. La unica diferencia radica en el operador flecha que aparece a continuación de los argumentos de role, el cual explicamos seguidamente.
1.- => El operador flecha indica al compilador de Dynamo que debe evaluar lo que se encuentra dentro de role antes de elegir la salida correcta para la iteración. Puede interpretarse como un trigger para ciertas funciones del compilador.
En el segundo ejemplo hemos realizado un filtrado multiobjeto y luego comparado resultados de uno y otro simultáneamente. Esta funcionalidad ha presentado inestabilidades que estamos solucionando. Utilízala con precaución o busca alternativas en tanto resolvemos el bug.
Como ya mencionamos, además de bucles y filtros, role también cunta con soporte nativo incorporado para Rangos. Vamos a ver dos ejemplos para demostrar lo sencillo que es utilizarlos y cuál es su sintaxis.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><h1>{=data.titles.iterators}</h1><section><ul><!-- [Dyn]: Implementación básica de un rango 'role'. [/Dyn] -->{>>role=(0 .. 6 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}<!-- [Dyn]: Una variante del ejemplo anterior. [/Dyn] -->{>>role=(2 .. 6 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}</ul><ul><!-- [Dyn]: Urilizando un Rango con condicionales internos y un indice inicial desconocido [/Dyn] -->{>>role=(i .. 7 -> products.prices)=>(products.prices.i < 100)$> <li class="green">[[value]]</li> >>(products.prices.i > 100 && products.prices.i < 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}<!-- [Dyn]: Similar al ejemplo anterior, agregando iteración multiobjeto en el Rango indicado** CUIDADO: ESTA FUNCIONALIDAD ESTÁ EN FASE EXPERIMENTAL ** [/Dyn] -->{>>role=(0 .. 7 -> [products.prices, breakClass])=>(products.prices.i < breakClass.i)$> <li class="green">[[value]]</li> >>(products.prices.i > breakClass.i && products.prices.i !== 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul></section></body></html>
Ahora que hemos presentado algunos ejemplos de cómo son los rangos, seguramente notaste que solamente tienen dos diferencias con los demás bucles. En general no dejan de ser bucles normales con dos variaciones:
1.- pos_inicio .. pos_fin Le indicas un iacute;ndice de inicio y uno de fin. En ese rango es en el que role iterará cada objeto. * Al igual que los demás bucles admite un carater alfasbético autoasignable como posición de inicio.
2.- .. Operador de role para indicarle que ejecute un rango entre el valor anterior y el posterior. * Ambas posiciones de inicio y final serán incluidas en la iteración.
Para finalizar este capítulo, vamos a mencionar algunas consideraciones generales que aplican a las estructuras de control, principalmente en lo referente a los bucles y rangos y que se deberín tener en cuenta al utilizar alguna de estas estructuras.
Esto significa que en las iteraciones multiobjeto, siempre prevalece como longitud máxima la que pertenece al objeto con menos elementos.
Por ejemplo: Suponiendo que has declarado un rango 0 .. 6 sobre dos objetos distintos y uno de ellos sólo contiene cinco elementos, role asumirá el final del rango cuando llegue al último elemento del objeto con menor longitud. Sería como si hubieras declarado el rango de esta forma 0 .. 4. Esto se aplica a todo tipo de bucles, no solamente al rango.
Esto significa que en las iteraciones, sobre todo en las de fitrado, role ignorará los índices que no existan.
Por ejemplo: Suponiendo que has declarado un filtro como este [prod1, prod4, prod7]. Asumiendo que prod4 no existe, lo saltará y continuará con el siguiente si lo hubiera.
Tanto esta característica como la anterior, son una medida de seguridad para evitar enviar errores al usuario y/o comportamientos inesperados.
Si bien Dynamo protege de errores de índice null o undefined, no significa que no devuelva valores de dichos tipos.
En el caso de que un índice exista en un elemento y su valor sea igual a 'null' o 'undefined' entonces sí lo tomará como una salida válida. Ya que asume que no se trata de un error de programación sino de algo deliberado.
Dynamo no cuenta, aún, con la posibilidad de definir funciones propiamente dichas por parte del usuario en su interface.
Sin embargo, dicha característica está planificada para ser agregada en próximas versiones. Podemos adelantar que su concepto es una conjunción de los Stored Procedures en SQL y los Schemas que se utilizan para trabajar con MongoDB. Además de agregar la capacidad para el tipado estático.
Visita la Guía de desarrollo para obtener más información sobre ésta y otras características.
Para facilitarte una visión de conjunto sobre todo lo que hemos tratado, te dejamos el código completo de Condicionales, Bucles y Rangos.
<html lang="en"><script src="path/to/litgirl/index.js" charset="utf-8" type="module" async defer></script><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Control Structures</title></head><body><h1>{=data.titles.iterators}</h1><aside class="sidebar"><ul><!-- [Dyn]: Ejemplo iteración simple sobre un objeto iterable con inicio numérico, sabiendo que su primer elemento tiene índice 0. [/Dyn] -->{>>role=(0 -> links)$> <li class="some-class">[[value]]</li> >>}<!-- [Dyn]: Ejemplo iteración simple sobre un objeto iterable con un caracter de asignación. Normalmente se utiliza cuando por alguna razón no se tiene certeza del valor del índice del primer elemento de un iterable. En los demás casos, automáticamente su valor inicial será asignado como 0. [/Dyn] -->{>>role=(i -> links)$> <li class="some-class">[[value]]</li> >>}</ul></aside><section><!-- [Dyn]: Ejemplo iteración sobre un iterable con filtrado por su índice. [/Dyn] -->{>>role=([1, 4, 7] -> images.url)$> <figure class="some-class"><img src="[[value]]" alt="" title=""></figure> >>}<!-- [Dyn]: Ejemplo iteración sobre un objeto con filtrado por sus propiedades. [/Dyn] -->{>>role=([prod1, prod4, prod7] -> images.url)$> <figure class="some-class"><img src="[[value]]" alt="" title=""></figure> >>}<div><!-- Este contenido HTML se mantiene inalterado --></div><!-- [Dyn]: Ejemplo iteración sobre dos objetos iterables desde su primer elemento hasta el último. [/Dyn] -->{>>role=(0 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}<!-- [Dyn]: Similar al ejemplo anterior, pero utilizando un filtrado. [/Dyn] -->{>>role=([1, 4, 7] -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}</section><section><ul><!-- [Dyn]: Ejemplo de 'role' con condicionales internos [/Dyn] -->{>>role=(i -> products.prices)=>(products.prices.i < 100)$> <li class="green">[[value]]</li> >>(products.prices.i > 100 && products.prices.i < 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul><ul><!-- [Dyn]: Similar al ejemplo anterior, agregando iteración multiobjeto y filtrado** CUIDADO: ESTA FUNCIONALIDAD ESTÁ EN FASE EXPERIMENTAL ** [/Dyn] -->{>>role=([0, 2, 3, 7] -> [products.prices, breakClass])=>(products.prices.i < breakClass.i)$> <li class="green">[[value]]</li> >>(products.prices.i > breakClass.i && products.prices.i !== 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul></section><section><ul><!-- [Dyn]: Implementación básica de un rango 'role'. [/Dyn] -->{>>role=(0 .. 6 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}<!-- [Dyn]: Una variante del ejemplo anterior. [/Dyn] -->{>>role=(2 .. 6 -> [links, images.url])$> <a href="[[link]]"><img src="[[image]]" alt="" title=""></a> >>}</ul><ul><!-- [Dyn]: Urilizando un Rango con condicionales internos y un indice inicial desconocido [/Dyn] -->{>>role=(i .. 7 -> products.prices)=>(products.prices.i < 100)$> <li class="green">[[value]]</li> >>(products.prices.i > 100 && products.prices.i < 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}<!-- [Dyn]: Similar al ejemplo anterior, agregando iteración multiobjeto en el Rango indicado** CUIDADO: ESTA FUNCIONALIDAD ESTÁ EN FASE EXPERIMENTAL ** [/Dyn] -->{>>role=(0 .. 7 -> [products.prices, breakClass])=>(products.prices.i < breakClass.i)$> <li class="green">[[value]]</li> >>(products.prices.i > breakClass.i && products.prices.i !== 500)$> <li class="orange"><strong>[[value]]</strong></li> >>out$> <li class="gray">Sin precio.</li> >>}</ul></section><footer></footer></body></html>
En los ejemplos que hemos visto a lo largo del capítulo, no se cubren absolutamente todos los aspectos del uso de las Estructuras de control en Dynamo. Aún así, esperamos que te sean de utilidad para una primeraq aproximación.
Juega con ellos, rompe todo lo que puedas y ¡Diviértete en el proceso! 😋
¿Tienes preguntas? Escríbenos a dev.litgirl@ohyoo.net
LitGirl © Equipo de Desarrollo - All rights reserved.