Qué es el Metacódigo

Plex está basado en la construcción de una aplicación mediante un modelo abstracto del problema. Este es el núcleo del producto, y la razón por la que obtiene ventajas incrementales a medida que un problema evoluciona y se hace más complejo. Este modelo podemos verlo como un repositorio que conserva información unificada de la lógica, la presentación, las relaciones entre objetos, las dependencias entre ellos, de modo que hasta la mínima parte suya (un nombre de objeto) es conocida por el conjunto instantáneamente.

En este marco, cuando deseamos implementar una determinada versión de nuestra aplicación, un corte en un estado de desarrollo del modelo, lo generamos. El código generado resultante es un subproducto del modelo, que usualmente no será nuestro foco de atención, salvo cuando debemos hacer tests detallados, pruebas enfocadas, estudios de performance. ésta justamente es su virtud.

Es en éste momento cuando interviene el metacódigo y sus metaoperaciones. Actúan como un conjunto de instrucciones abstractas enviadas al generador. ¿Qué es el generador? Es el motor que genera el código específico de los objetos implementables (El generador de una descripción de archivo: DDS, SQL, de un programa: RPG, C++, Java), que actúa consultando el modelo para implementar el objeto elegido. En este marco, el metacódigo inserto en los diagramas de acción permite dar un paso más en la abstracción: Adecuar una lógica básica descripta en el diagrama, a condiciones particulares que el metacódigo describe, o desplegar operaciones descriptas en un modo general. El metacódigo se aplica sobre el modelo en tiempo de diseño, no sobre el código en ejecución. Las metainstrucciones aplican su operación al modelo, expandiendo el código generado en base al contexto del modelo. Así, una metaoperación puede variar en el código generado según la variable sobre la que se aplique, la variante, el lenguaje, etc.

Entonces, qué NO es el metacódigo: No es un conjunto de instrucciones para efectuar operaciones en tiempo de ejecución. Nada de lo que yo use será interpretado o decodificado durante la ejecución de la aplicación. Existen otras vías para hacer acciones limitadas de este tipo, pero el metacódigo actúa exclusivamente durante la generación del código fuente: lee el diagrama de acción, toma las metainstrucciones, e interroga al modelo para decidir cómo aplicarla.

No se desarrolla en este sitio un tutorial, simplemente porque existen tres excelentes elementos para capacitarse: la ayuda de Plex, el ofrecido por Adrian Slade, y el desarrollado por Rik Crompton. Si usted necesita un tutorial de Metacódigo: Siempre existió el escrito por Adrian Slade, pero ahora solo es posible verlo en el sitio de Yuri Lesiuk. Como desde siempre, el tutorial se detiene en el capítulo de Queries, pero sigue siendo no sólo útil, sino único
Información adicional, apuntando a tópicos específicos, existe en el sitio de Lucio Gayosso.
Un buen y claro tutorial está disponible en el sitio de Rik Crompton.

Casos de uso de Metacódigo

Operar sobre un elemento de un array
Le debo el caso a Mario Zoppellari, de Italia. Aplicado en el ejemplo a un campo en una grilla que es un arreglo, donde se desea cambiar el estado de uno de los elementos, basado en una condición. El caso es que no es posible aplicar un SET STATE a un elemento de un arreglo, ya que al apuntar al número de elemento, el analizador de sintaxis da un error. El problema en palabras de Tim Wiens:
I have a grid that contains an array field. Evidently I can't Set State on these fields? For example: Set State Hidden, GridP[Value Array], Local[Index] won't work because the second comma causes an error. Am I missing something? Is there a work around?
La solución ofrecida por Mario:
You must use meta code. If you have only the Array field on GridP, you can use this: 
		

Set Local = Counter.*One
+For Each Field GridP
+For Each Field Component
If "Condition to hide element" IS True
++Set State Hidden
Set Local = Local + Counter.*One

If you have other fields on GridP, you must test that the corrent field on meta-loop '+For Each Field GridP', is your array field
Puede ver la discusión completa en EDGE
Obtener el nombre del valor de un campo
Explicado inicialmente por Adrian Smith, y luego mejorado con algunas variantes: Se trata de obtener el nombre de un valor en el modelo, a partir de la constante literal que lo representa, el mismo que se lee en un combo o list box, pero sin desplegar el campo list o combo, sino en cualquier edit o similar. Aquí está el código y una alternativa creada por Miguel Almeda:
I wanted to put out the long value for a field, without using a combo box on screen. When I used a straightforward Edit field, this gave me the short (Internal) value.
	
	+++Define Field: +Value
+For Each Field Input
+For Each Property Target FLD value VAL
+++Set Value To Current Field: +Value
++Text Defined Field: +Value, WorkL
If WorkL == Input
++Name Defined Field: +Value, Output, .Unscoped
La variante ingresada por Miguel Almeda:
	The same meta-loop with a small optimitation.
+++Define Field: +Value
+For Each Field Input
+For Each Field Value
+++Set Value To Current Field: +Value
++If Value Filed: +Value
++Name Defined Field: +Value, Output< ConditionText >, .Language
This works the same but it generates one line less for each value of the field, and avoids any local variable.

Si bien la fuente original de este caso se perdió el día que el antiguo repositorio de EDGE se descartó, conservo en mi sitio una copia con su contenido.
Actualizar condicionalmente los campos de una vista
El problema: Se desea actualizar los datos de una vista sólo si no tienen datos ya informados, tomando alguna acción si al intentar actualizar, existen valores. La vista tiene un gran número de campos, por lo que el código va a ser largo. Entonces, hacerlo de una manera abstracta. Aquí está la solución ofrecida por Crispin Bates, en el viejo foro Edge ya destruído:
Sub Test

Comment Determine which fields are empty in View
+For Each Field View
Set CountL = CountL +
Use EmptyL, CountL
++If Empty
Set EmptyL =
++Else
Set EmptyL =
Set CountL =
+++Define Field: FIELDS/+Field
+For Each Field Input
+++Set Value To Current Field: FIELDS/+Field
Set CountL = CountL +
Use EmptyL, CountL
++If Empty
Comment Input field is Empty
++Else
++If NE View
Comment NE View field value
If EmptyL ==
View field is empty so update with input
++Cast To View, Field: FIELDS/+Field
Else
Comment View is not empty so error

Conservo una copia de la discusión completa, que puede consultar aquí.

Una variante: copiar valores entre variables (igual campo) condicionalmente
El problema: dadas dos variables que pueden contener campos iguales (Dato_a en variable_1 y variable_2), copiar de variable_1 a variable_2 si en variable_1 hay datos.