&
 Evaluación de macro-unario                      (Especial)
------------------------------------------------------------------------------
 Sintaxis

     &<cVarMacro>[.]
     &(<cExpMacro>)

 Operandos

     <cVarMacro> puede ser cualquier variable de caracteres. El punto
     (.) es el terminador de macro e indica el final de la variable de
     macro y lo distingue de cualquier texto adyacente en la sentencia.

     <cExpMacro> es una expresión de caracteres escrita entre
     paréntesis. En este ejemplo, la expresión se evalúa primero y la
     operación de la macro se ejecuta en el valor de caracteres resultante.
     Esto permite compilar y ejecutar el contenido de campos y elementos de
     una matriz.

 Descripción

     El operador de macro en CA-Clipper es un operador especial que permite
     la compilación de expresiones durante la ejecución y la sustitución de
     texto dentro de cadenas. Cuando se encuentra un operador de macro (&),
     el operando se envía a un compilador especial de ejecución (el
     compilador de macros) que compila expresiones pero no sentencias o
     mandatos.

 Sustitución de texto

     Siempre que una referencia a una variable de macro pública o privada se
     encuentre intercalada en una cadena de caracteres, la referencia a la
     variable se sustituye por el contenido de la variable de macro. Por
     ejemplo:

     cMacro := "Manuel"
     ? "Hola &cMacro"                // Resultado: Hola Manuel

     Si especifica una expresión de macro (p. e. & (cMacro1+cMacro2)) y la
     variable de macro es una variable local, estática, de campo o un
     elemento de matriz, se trata como texto literal y no se amplía.

 Compilación y ejecución

     Cuando se encuentra una variable o expresión de macro dentro de una
     expresión, se trata como una expresión, y el símbolo de macro se
     comporta como operador de compilación y ejecución. Si la macro se
     especifica como una variable de macro:

     cMacro := "DTOC(FECHA())"
     ? &cMacro

     el compilador de macros compila y ejecuta el contenido de la variable
     de macro y se desecha el código compilado a continuación.

     Si especifica una expresión escrita entre paréntesis y precedida del
     operador de macro (&),

     ? &(INDEXKEY(0))
     la expresión se evalúa y la cadena de caracteres resultante se compila
     y ejecuta como una variable de macro.

     Utilizando un operador de macro, puede compilar una cadena de
     caracteres que contenga una definición de bloque de código:

     bBloque := &("{ |exp| QOUT(exp) }")

     La parte que ejecuta la operación devuelve como valor el bloque de
     código. Puede utilizar este bloque de código invocándolo con la función
     EVAL(). Esto es especialmente importante en procedimientos que
     requieran bucles muy grandes de condiciones definidas por el usuario
     (operaciones que en las versiones anteriores de CA-Clipper precisaban
     una expansión de macros). En estas versiones, las expresiones de macro
     se compilaban y evaluaban en cada iteración del bucle. Al combinar la
     expansión de macros y la función EVAL() con el bloque de código, la
     compilación se realiza sólo una vez, y EVAL() simplemente ejecuta el
     bloque de código cada vez en el bucle.

     EVAL(bBloque, DATE())

     Se puede ahorrar así muchísimo tiempo en la ejecución.

 Notas


     ■ Palabras clave de mandato: No puede utilizar el operador de
        macro (&) para sustituir o compilar palabras clave de mandato. No
        obstante, es posible redefinir estas palabras clave modificando la
        definición de mandato en Std.ch, anulando una definición de mandato
        existente con una nueva definición mediante la directiva #command o
        redefiniendo la palabra clave de mandato utilizando la directiva
        #translate. En cualquier caso, sólo puede redefinir estas palabras
        clave durante la compilación y no en la ejecución.


     ■ Argumentos de mandato: En las versiones anteriores de
        CA-Clipper, así como en otros dialectos, podía utilizar variables de
        macro como argumentos de mandatos que utilizaban valores literales
        de texto. Estos incluían todos los mandatos de ficheros y mandatos
        SET con argumentos alternativos. En tales casos, ahora puede
        utilizar una expresión ampliada escrita entre paréntesis, en vez del
        argumento literal. Por ejemplo,

        xcBaseDatos = "Facturas"
        USE &xcBaseDatos.

        puede sustituirse por:

        xcBaseDatos = "Facturas"
        USE (xcBaseDatos)

        Es importante utilizar expresiones ampliadas si utiliza variables
        estáticas y locales. Normalmente, los mandatos se preprocesan en
        llamadas a funciones, y los argumentos de mandatos se traducen en
        argumentos de funciones como valores válidos de CA-Clipper. Los
        nombres de ficheros en los mandatos de ficheros, por ejemplo, se
        convierten en cadenas utilizando el patrón de salida inteligente
        convertido a cadena y se pasan como argumentos a las funciones que
        realmente ejecutan las acciones deseadas. Si especifica un valor
        literal o de macro como argumento de mandato, se convierte en una
        cadena. No obstante, si el argumento es una expresión ampliada, se
        escribe en el resultado exactamente como se había especificado. Este
        ejemplo,

        #command RENAME <xcAnterior> TO <xcNuevo>;
        =>;
              FRENAME( <(xcAnterior)>, <(xcNuevo)> )
        //
        RENAME &xcAnterior TO &xcNuevo
        RENAME (xcAnterior) TO (xcNuevo)

        se escribe como:

        FRENAME( "&xcAnterior", "&xcNuevo" )
        FRENAME( xcAnterior, xcNuevo )

        en el preproceso. Cuando las variables de macro se convierten a
        cadenas, los nombres de variable de macro se ocultan en la cadena y
        no se compilan. Posteriormente, durante la ejecución, se sustituyen
        por la cadena y se pasan como argumentos a la función FRENAME().
        Esto finaliza con las variables de macro locales y estáticas, dado
        que los nombres de variables no están presentes para ser sustituidos
        durante la ejecución. Las variables públicas y privadas, no
        obstante, se comportan según lo esperado.


     ■ Listas como argumentos de mandato: El operador de macro (&) no
        sustituye ni compila completamente una lista como argumento de la
        mayoría de los mandatos mi, en concreto, en aquellos en los que una
        lista de argumentos se preprocesa en una matriz o bloque de código.
        Ejemplos de ello son los argumentos de la cláusula FIELDS y SET
        INDEX. El mandato SET COLOR que preprocesa la lista de colores en
        una sola cadena de caracteres y la pasa a la función SETCOLOR() es
        una excepción.

        En cualquier caso, las listas de argumentos deberían especificarse
        siempre como expresiones extendidas especificando cada lista de
        argumentos:

        LOCAL xcIndice := { "Ntx1", "Ntx2" }
        SET INDEX TO (xcIndice[1]), (xcIndice[2])


     ■ Matrices: Puede utilizar el operador de macro (&) con matrices
        y elementos de matrices. No obstante, debido a la mayor potencia de
        las matrices de CA-Clipper, probablemente podrá prescindir
        generalmente del operador de macro (&) para hacer referencias a
        matrices. Ahora puede asignar referencias de matrices a variables,
        devolver referencias a matrices desde funciones definidas por el
        usuario y anidar referencias a matrices dentro de otras matrices.
        También puede crear matrices especificando matrices literales o
        utilizando la función ARRAY().

        Por tanto, puede hacer referencias a matrices y a elementos de una
        matriz utilizando variables de macro y expresiones de macro, con la
        única restricción de que no se aceptan referencias de subíndice en
        una sentencia PRIVATE o PUBLIC. Tampoco puede especificar el
        operador de macro (&) en una declaración, tal como una sentencia
        LOCAL o STATIC. Si lo hiciera, se generaría un error grave del
        compilador.

        En este ejemplo se hacen referencias a elementos de matriz con
        variables de macro:

        cNombre := "aMatriz"
        nElementos := 5
        cNombreElemento := "aMatriz[1]"
        //
        PRIVATE &cNombre.[nElementos]           // Crea una "matriz" con 5
                                                // elementos
        &cNombreElemento. := 100                // Asigna 100 al elemento 1
        &cNombre.[3] := "abc"                   // Asigna "abc" al
                                                // elemento 3

        Puede aplicar con éxito un operador de macro (&) a un elemento de
        matriz si se utiliza una referencia con una expresión de macro. No
        obstante, las referencias a variables de macro generan un error de
        ejecución. Por ejemplo, el fragmento siguiente lista los valores de
        todos los campos en el registro actual:

        USE Cliente NEW
        aEstruc := DBSTRUCT()
        //
        FOR nCampo := 1 TO LEN(aEstruc)
           ? &(aEstruc[nCampo, 1])
        NEXT

     ■ Bloques de código: En la mayoría de los casos, puede aplicar
        el operador de macro (&) a una variable o expresión contenida en un
        bloque de código. Existe una restricción cuando la variable de macro
        o expresión de macro contiene una variable declarada. Se produce un
        error de ejecución si especifica una expresión compleja (una
        expresión que contiene un operador y uno o más operandos) que
        incluya el operador de macro (&) en el bloque de código.

        Esto tiene importantes implicaciones en la utilización de las
        variables locales y estáticas en las cláusulas condicionales de
        mandatos, dado que estas cláusulas se convierten durante el
        preprocesado en bloques de código exactamente como están escritas.
        Esto se aplica a todas las cláusulas FOR y WHILE, al mandato SET
        FILTER y a la expresión de relación SET RELATION. La posible
        solución consiste en reunir toda la expresión en una sola variable
        de macro y aplicar a continuación el operador de macro (&) a la
        variable.


     ■ Condiciones de macro: Al utilizar el operador de macro (&)
        para especificar cláusulas condicionales de mandatos de base de
        datos, como cláusulas FOR y WHILE, es preciso tener en cuenta
        algunas limitaciones impuestas por la complejidad y tamaño de la
        expresión:

        - El compilador no puede procesar cadenas que excedan de los 254
           caracteres.

        - Existe un límite en la complejidad de las condiciones (cuanto
           más complejas, puede especificar menor número de condiciones).

     ■ Procedimientos y funciones: Es posible referenciar llamadas a
        procedimientos y funciones utilizando variables y expresiones de
        macro. Con DO, la referencia de variable de macro al procedimiento
        puede ser el nombre completo del procedimiento o sólo una parte. Con
        una llamada a una función (incorporada o definida por el usuario),
        la referencia de variable de macro debe incluir el nombre de la
        función y todos sus argumentos.

        En CA-Clipper, debido a las facilidades añadidas de bloques de
        código, todas las invocaciones de funciones y procedimientos que
        utilizan el operador de macro deberían convertirse para la
        evaluación de bloques de código. Este fragmento de código:

        cProc := "InfoCuentas"
        .
        .
        .
        DO &cProc

        puede sustituirse por:

        bProc := &( "{ || InfoCuentas() }" )
        .
        .
        .
        EVAL(bProc)

        La ventaja de un bloque de código sobre una evaluación de macro
        radica en que es posible guardar el resultado de la compilación de
        una cadena que contiene un bloque de código, por lo que sólo es
        necesario compilarla una vez. Las evaluaciones de macro se compilan
        cada vez que se referencian.

     ■ Referencias a overlays: Es necesario declarar los
        procedimientos y las funciones definidas por el usuario que se
        utilizan en expresiones y variables de macro pero que no se
        referencian en ningún sitio con EXTERNAL, pues de lo contrario el
        enlazador no las incluirá en el fichero ejecutable (.EXE).

     ■ TEXT...ENDTEXT: Las variables de macro referenciadas dentro de
        una estructura TEXT...ENDTEXT se expanden. Recuerde que un campo no
        puede expandirse, por lo que debe asignar primero el valor de campo
        a una variable de memoria y luego referenciar la variable de memoria
        como una variable de macro dentro de la estructura TEXT...ENDTEXT.
        Por ejemplo:

        USE Cliente NEW
        miVar := Cliente->NomCliente
        TEXT
        Este es el texto con una macro &miVar
        ENDTEXT

     ■ Macros anidadas: El proceso de las variables y expresiones de
        macro en CA-Clipper permite anidar las definiciones de macro. Por
        ejemplo, después de asignar una variable de macro a otra variable de
        macro es posible expandir la variable de macro original, provocando
        con ello la expansión de la segunda variable de macro y la
        evaluación de su contenido:

        cUno = "&cDos"               // expande cDos
        cDos = "cTres"               // y produce "cTres"
        cTres = "hola"
        //
        ? &cUno                      // Resultado: "hola"

 To download this example - click here.

See Also: ( )