close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Changes between Version 1 and Version 2 of NameBlock


Ignore:
Timestamp:
Feb 27, 2009, 10:09:33 AM (16 years ago)
Author:
Víctor de Buen Remiro
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • NameBlock

    v1 v2  
    2121== Reglas sintácticas ==
    2222
    23 1. Reglas de declaración de un NameBlock
     23=== 1. Reglas de declaración de un NameBlock ===
    2424
    2525        * 1.1. La sintaxis de definición de un NameBlock admite únicamente tres posibles formas BNF, de las cuales se dan más detalles en los apartados posteriores:
     
    132132                NameBlock BadNS_1.3.5 = [[Real x]];
    133133}}}
     134
     135=== 2. Reglas de acceso a miembros ===
     136
     137        * 2.1. Para acceder a los miembros públicos se usará el nombre del NameBlock con el operador especial
     138
     139           
     140          Anything nameblock_id::public_member_id
     141
     142          Siguiendo con el ejemplo del punto 1.2 anterior:
     143{{{
     144          Real MyNS_1.2::_.exported_1;
     145          Real MyNS_1.2::_.exported_2;
     146          Real MyNS_1.2::fun_a(MyNS_1.2::_.exported_1);
     147          Set table =
     148          [[
     149            MyNS_1.2::mystr(1,"uno"),
     150            MyNS_1.2::real2mystr(4.0),
     151            MyNS_1.2::real2mystr(Pi)
     152          ]];
     153}}}
     154  * 2.2. Evidentemente no se puede acceder con :: a los miembros privados. Ejemplo de uso inválido:
     155{{{
     156    Real MyNS_1.2::_aux_1; 
     157    Real MyNS_1.2::_fun_aux(1);
     158}}}
     159  * 2.3. En ningún caso es posible acceder a los miembros públicos ni privados de un NameBlock mediante los operadores de acceso a Set Set[Real], Set[Text],y aún menos con Set->field_name puesto que no puede existir un NameSpace con estructura. Ejemplo de uso inválido:
     160{{{
     161    Real MyNS_1.2[3];
     162    Real MyNS_1.2["exported_2"];
     163    Real BadNS_2.3->x_;
     164}}}
     165  * 2.4. Nótese que el concepto de miembro se extiende tan sólo a los elementos a primer nivel del conjunto base de un NameBlock, y no al resto de elementos de su jerarquía recursiva de subconjuntos aunque tengan nombre accesible desde el nivel del conjunto.
     166    Ejemplo de uso inválido:
     167{{{
     168    NameBlock MyNS_2.4 =
     169    [[
     170      Set a = [[ Real a1 = 1; Real a2 = 2 ]]
     171    ]];
     172    Real MyNS_2.4::a1; 
     173}}}
     174
     175=== 3. Reglas de anidación ===
     176
     177        * 3.1. Para poder acceder de modo recursivo a los NameBlock's, estos pueden estar anidados como en este nuevo. Ejemplo:
     178{{{
     179          NameBlock MyNS_3.1 =
     180          [[
     181            NameBlock a = [[ Real a1 = 1; Real a2 = 2 ]]
     182          ]];
     183          Real MyNS_3.1::a::a1; 
     184}}}
     185        * 3.2. Un modo especialmente práctico que puede ayudar a la organización del código sería usar el Include como en el siguiente ejemplo 3.2
     186{{{
     187          //Fichero ns1.tol
     188          ...
     189
     190          NameBlock NS1 = [[
     191          Real _aux_1 = 1;
     192          Real _aux_2 = 2;
     193          Real a = _aux_1+_aux_2;
     194          Real b = _aux_1-_aux_2
     195          ]];
     196          ...
     197
     198          //Fichero ns2.tol
     199          ...
     200          NameBlock NS2 = [[
     201          Real _fun_aux(Real x) { x*4 };
     202          Real fun_a(Real x) { _fun_aux(x)+1 };
     203          Real fun_b(Real x) { _fun_aux(x)-1 }
     204          ]];
     205          ...
     206
     207          //Fichero MyNS_3.2.tol
     208          NameBlock MyNS_3.2 =
     209          [[
     210          //Private:
     211            Set _ns1 = Include("ns1.tol");
     212            Set _ns2 = Include("ns2.tol");
     213          //Public:
     214            NameBlock NS1;
     215            NameBlock NS2
     216          ]];
     217}}}
     218          Obsérvese que sólo se publican NS1y NS2 por lo que cualquier cosa definida en ns1.tol y ns2.tol distinta de ellos permanecerá inaccesible externamente.
     219        * 3.3. Para mayor comodidad se puede renombrar externamente un NameBlock anidado con un alias identificativo más corto que la concatenación completa de NameBlock's, como se ha visto en el punto 1.1.3. Esto evita tener que escribir demasiados nombres largos que dificulten la lectura. Pero se debe usar siempre de forma cuidadosa, cuando no dé lugar a ambigüedades y siempre en código de usuario final, nunca en librerías de funciones de uso general, pues en tal caso destruye los principios de organización y modularidad que es uno de los principales objetivos de NameBlock.
     220
     221          En un programa concreto de usuario que va a hacer uso intensivo de un NameBlock de nombre muy largo se podría considear razonable crear un alias como por ejemplo:
     222{{{
     223          NameBlock _aia = std::math::stat::model::mle::arima::aia;
     224}}}
     225
     226=== 4. Reglas de publicación o globalización ===
     227
     228        * 4.1.En determinadas circunstancias los miembros públicos o de sólo lectura de un NameBlock pueden pasar al ámbito global, es decir, se puede acceder a ellos sin explicitarlo con ::. A este hecho se le llamará publicar un NameBlock y se logra con el operador Real UsingNameBlock(NameBlock nameblock_idt) y es similar al using namespace de C++, aunque con ciertas diferencias.
     229        * 4.2.El operador UsingNameBlock devuelve cierto si es compatible con el resto de variables de tipo NameBlock actualmente globalizadas, es decir, si no contiene ningún miembro público con el mismo nombre que otro. Los miembros que ya estuvieran presentes no serán accesibles de forma implícita pero sí mediante ::, y se mostrará un mensaje de aviso para advertirlo.
     230        * 4.3.Como es lógico, este operador de globalización no surte efecto si se llama en ambiente local, lo cual incluye dentro de un NameBlock, y devolverá falso y un mensaje de error si se intenta.
     231        * 4.4.El NameBlock permanecerá en uso mientras siga existiendo el objeto devuelto por este operador. Por ejemplo, si se ha incluido en un fichero estará presente hasta que se descompile dicho fichero.
     232        * 4.5.Si existe una variable global previa con el mismo nombre ocultará el miembro NameBlock publicado que seguirá siendo accesible con ::, como es lógico. Si se crea la variable global posteriormente se actuará del mismo modo.
     233        * 4.6.Se trata de una sentencia no declarativa sino ejecutiva por lo que no tiene efecto si se recupera de un módulo OIS.
     234        * 4.7.Al igual que con los alias del apartado 3.3., se debe ser sumamente cauteloso con este tipo de sentencias y no incluirlas en librerías de caracter general. Sería prudente usarlas sólo en programas de usuario final y cuando no haya ninguna posible ambigüedad de nomenclatura. Puede ser particularmente útil para mantener compatibilidad hacia atrás de código creado previamente a la existencia de NameBlock.
     235
     236=== 5. Reglas de ámbito ===
     237    Un NameBlock tiene su propia tabla de símbolos que se usa cuando está activo, es decir, cuando se está ejecutando alguna de sus funciones miembro. Sólo puede haber activo un NameBlock al mismo tiempo o bien no haber ninguno activo en cuyo caso todo funciona como hasta ahora. El orden de búsquedas de símbolos de TOL que anteriormente se reducía a símbolos de ámbito local y ámbito global, pasa a ser el siguiente:
     238
     239        * 5.1. Miembro local: Si hay un NameBlock activo se busca ahí.
     240        * 5.2. Ámbito local: Si no lo había o bien no contiene el nombre buscado y estamos en ambiente local se busca en la pila local.
     241        * 5.3. Ámbito global: Si aún no se ha encontrado nada en los dos puntos anteriores se busca en la tabla global de símbolos.
     242        * 5.4. Miembro publicado: Si sigue sin encontrarse el símbolo se buscará en la tabla de NameBlock publicados.
     243
     244    Cuando se llama a una función de un NameBlock se activa el mismo y la búsqueda de variables, funciones y estructuras locales le da total prioridad a los miembros de ese NameBlock de forma que se pueden usar todos ellos, tanto públicos como privados.
     245
     246    Esto reduce el uso actual de scope dinámico en la pila local de llamadas de funciones, lo cual puede ayudar a medio plazo a reconducir a los usuarios de TOL a los estándares de programación.
     247
     248=== Ventajas ===
     249
     250Las ventajas que aportan los NameBlock's se pueden resumir en que da facilidades para alcanzar mayor modularidad, mejor organización y legibilidad y mayor reusabilidad del código.
     251
     252==== Modularidad ====
     253
     254    La principal utilidad del NameBlock es dotar a TOL de un mecanismo de modularidad más allá del fichero que permita construir módulos, paquetes y librerías robustamente organizados. Una forma prudente de anidar los NameBlock's sería en este caso: lib_id::package_id::module_id
     255Legibilidad
     256    Pero un NameBlock podría también ayudar a la legibilidad del código en tareas más humildes, al sustituir llamadas a set[num_field] por set::name_field sin el coste computacional añadido de set["name_field"] y sin tener que definir estructuras de datos espúreas para usar set->name_field
     257Eliminación de variables globales
     258    Un caso especialmente recomendable es el que afecta a todos los parámetros de configuración y variables globales en general que deberían incluirse dentro de un único NameBlock global para evitar colisiones de nombres.
     259
     260    //Parámetros de configuración del proyecto
     261    NameBlock cfg =
     262    [[
     263    //Configuración del acceso a la base de datos
     264      NameBlock db   = [[Text alias, Text user, Text pwd, Text host, ...]],
     265    //Configuración de los directorios más utilizados
     266      NameBlock path = [[Text source, Text data, Text log, ...]],
     267      ...
     268    ]];
     269    Real DBOpen(cfg::db::alias, cfg::db::user, cfg::db::pwd);
     270
     271==== Flexibilidad ====
     272
     273    Las funciones que devuelven conjuntos heterogéneos también ganarían flexibilidad, expresibilidad y facilidad de mantenimiento y uso sin recurrir a la definición de estructuras locales
     274
     275    NameBlock my_stats(Serie ser)
     276    {[[
     277      Real num  = CountS (ser);
     278      Real avg  = AvrS(ser);
     279      Real stdv = StDsS(ser)   
     280    ]]};
     281
     282    NameBlock stats = my_stats(SubSer(Gaussian(0,1,C),y2000,y2000m12d31));
     283    Real stats::stdv;
     284
     285    Aunque se añadan elementos a lo que devuelve la función o se reordenen los mismos seguirá funcionando el código que usara esta función accediendo con :: mientras no se cambien los nombres:
     286
     287    NameBlock my_stats(Serie ser)
     288    {[[
     289      Real num  = CountS (ser);
     290      Real avg  = AvrS(ser);
     291      Real mdn  = MedianS(ser);
     292      Real stdv = StDsS(ser)   
     293    ]]};
     294
     295==== Generación automática de documentación ====
     296    A efectos de generación automática de documentación de un NameBlock, se cuenta con la función Set Members(NameBlock root) que devuelve un listado de los miembros públicos contenidos en un NameBlock y sus hijos de forma recursiva, con un registro para cada uno con la siguiente estructura informativa ordenada de la forma natural indicada por los propios campos:
     297{{{
     298    Struct NameBlockInfoStruct
     299    {
     300      Text nameBlock_,   //full name block path a::b::...
     301      Text mode_,        //"Variable", "Function" or "Struct"
     302      Text grammar_,     //"Real", "Text", "Set", "NameBlock", ...
     303      Text memberName_,  //Internal public member name
     304      Text filePath_,    //Relative path to the root file path
     305      Text description_  //User description
     306    };
     307}}}
     308===== Miembros de documentación accesibles de sólo lectura =====
     309    Son miembros de sólo lectura de la forma _.autodoc.<sufix>
     310
     311        * _.autodoc.description: Si un NameBlock contiene un miembro privado Text _.autodoc.description, entonces su contenido pasa a ser la descripción del NameBlock sin necesidad de usar la función PutDescription.
     312        * _.autodoc.keys: Si un NameBlock contiene un miembro privado Set _.autodoc.keys, entonces sus elementos, que han de ser todos de tipo Text, pasan a ser palabras claves utilizadas en los procedimientos de búsqueda temática.
     313        * _.autodoc.url: Si un NameBlock contiene un miembro privado Text _.autodoc.url este se usará en los mecanismos de generación automática para enlazar a la URL especificada en la que se explicará de forma más detallada el funcionamiento del NameBlock.
     314        * _.autodoc.authors: Si un NameBlock contiene un miembro privado Set _.autodoc.authors este se usará en los mecanismos de generación automática para identificar a los autores del código.
     315
     316===== Funciones de información relacionadas =====
     317
     318        * Text GetNameBlock(Anything obj): Devuelve el nombre completo del NameBlock al que pertenece un objeto. Si no pertenece a ninguno devuelve la cadena vacía "".
     319        * Text FullName(Anything obj): Devuelve el nombre completo de un objeto, incluyendo el prefijo de su NameBlock si está dentro de uno.
     320
     321