versión 2003 (Modificado)
El compilador espera las reglas de sintaxis habituales de los comandos 4D, no necesita modificaciones especiales para bases que van a ser compiladas.
Sin embargo esta sección ofrece algunos recordatorios y detalles específicos:
Algunos comandos que influyen en el tipo de una variable pueden, si no tiene cuidado, conducir a conflictos.
Algunos comandos utilizan más de una sintaxis o parámetros, es importante saber cuál es el más apropiado.
Cadenas de caracteres
Character code (carácter)
Para los comandos que operan sobre cadenas, sólo la función Character code requiere atención especial. En modo interpretado, puede pasar indiferentemente una cadena no vacía o vacía a esta función.
En modo compilado, no puede pasar una cadena vacía.
Si pasa una cadena vacía y el argumento pasado a Character code es una variable, el compilador no podrá detectar un error en la compilación.
Comunicaciones
SEND VARIABLE(variable)
RECEIVE VARIABLE(variable)
Estos dos comandos se utilizan para escribir y recibir variables enviadas al disco. Las variables se pasan como parámetros a estos comandos.
El parámetro que pasa debe ser siempre del mismo tipo. Suponga que quiere enviar una lista de variables a un archivo. Para eliminar el riesgo de cambiar los tipos de datos involuntariamente, recomendamos especificar al principio de la lista el tipo de las variables enviadas. De esta forma, cuando usted recibe estas variables, siempre comenzará por obtener un indicador. Luego, cuando llama a RECEIVE VARIABLE, la transferencia se maneja por intermedio de una instrucción Case of.
Ejemplo:
SET CHANNEL(12;"Archivo") If (OK=1) $Tipo:=Type([Cliente]Total_A) SEND VARIABLE($Tipo) For($i;1;Records in selection) $Enviar_A:=[Cliente]Total_A SEND VARIABLE($Enviar_A) End for End if SET CHANNEL(11) SET CHANNEL(13;"MiArchivo") If (OK=1) RECEIVE VARIABLE($Tipo) Case of :($Tipo=Is String Var) RECEIVE VARIABLE($Cadena) `Proceso de la variable recibida :($Tipo=Is Real) RECEIVE VARIABLE($Real) `Proceso de la variable recibida :($Tipo=Is Text) RECEIVE VARIABLE($Text) `Proceso de la variable recibida End case End if SET CHANNEL(11)
Acceso estructural
Field (puntero campo) o (tabla número;campo número)
Table (puntero tabla) o (tabla número) o (puntero campo)
Estos dos comandos devuelven los resultados de diferentes tipos de datos, de acuerdo a los parámetros pasados:
Si pasa un puntero a la función Table, el resultado devuelto es un número.
Si pasa un número a la función Table, el resultado devuelto es un puntero.
Las dos funciones no son suficientes para que el compilador determine el tipo del resultado. En tales casos, utilice una directiva de compilación para evitar cualquier ambigüedad.
Documentos
Recuerde que las referencias del documento devuelto por las funciones Open document, Append document y Create document son de tipo Hora.
Matemáticas
Mod (valor;divisor)
La expresión "25 modulo 3" puede escribirse de dos formas diferentes en 4d:
Variable:=Mod(25;3)
o
Variable:=25%3
El compilador ve una diferencia entre las dos: Mod aplica a todos los tipos numéricos, mientras que el operador % aplica únicamente a Enteros y Enteros largos. Si el operando del operador % excede el rango de los Enteros largos, el resultado devuelto probablemente será errado.
Excepciones
IDLE
ON EVENT CALL (Method{; ProcessName})
ABORT
ON EVENT CALL
El comando IDLE ha sido añadido al lenguaje 4D para manejar excepciones. Este comando debe utilizarse cuando utilice el comando ON EVENT CALL.
Este comando puede definirse como una directiva de gestión de eventos.
Sólo el kernel (núcleo) de 4D puede detectar un evento sistema (clic del ratón, actividad del teclado, etc.). En la mayoría de los casos, las llamadas al kernel son iniciadas por el mismo código compilado, de una manera transparente para el usuario.
Por otra parte, cuando 4D está esperando pasivamente por un eventopor ejemplo, en un bucle de esperaes evidente que no habrá ninguna llamada.
Ejemplo bajo Windows
`Método de proyecto ClicRaton If (MouseDown=1) <>vPrueba:=True ALERT("Alguien hizo clic en el ratón") End if `Método Espera <>vPrueba:=False ON EVENT CALL("ClicRaton") While(<>vPrueba=False) `Bucle de atención del evento End while ON EVENT CALL("")
En este caso, se añade el comando IDLE de la forma siguiente:
`Método Espera <>vPrueba:=False ON EVENT CALL("ClicRaton") While(<>vPrueba=False) IDLE `Llamar al Kernel para detectar un evento End while ON EVENT CALL("")
ABORT
Utilice este comando sólo en métodos de proyecto de intercepción de errores. Este comando funciona exáctamente como en 4D, excepto en un método que ha sido llamado por uno de los siguientes comandos: EXECUTE FORMULA, APPLY TO SELECTION y APPLY TO SUBSELECTION. Trate de evitar esta situación.
Arrays
Siete comandos de 4D son utilizados por el compilador para determinar el tipo de un array:
COPY ARRAY(fuente;destino)
SELECTION TO ARRAY(campo;Array)
ARRAY TO SELECTION(Array;campo)
SELECTION RANGE TO ARRAY(inicio;fin;campo;Array)
LIST TO ARRAY(lista;Array{; itemRefs})
ARRAY TO LIST(Array;lista{; itemRefs})
DISTINCT VALUES(campo;Array)
COPY ARRAY
El comando COPY ARRAY acepta dos parámetros de tipo Array. Si uno de los parámetros de array no ha sido declarado, el compilador determina el tipo del array no declarado según el tipo del declarado.
Esta deducción se realiza en los dos casos siguientes:
El array declarado es el primer parámetro. El compilador asigna el tipo del primer array al segundo array.
El array declarado es el segundo parámetro. En este caso, el compilador asigna el tipo de dato del segundo array al primer array.
Como el compilador es estricto con los tipos, COPY ARRAY sólo puede hacerse desde un array de un cierto tipo a un array del mismo tipo.
Por lo tanto, si quiere copiar un array de elementos cuyos tipos son similares, es decir, Enteros, Enteros largos y Reales, o Texto y Alfas, o Alfas de diferentes longitudes, tiene que copiar los elementos uno por uno.
Imagine que quiere copiar elementos de un Array Entero a un Array Real. Puede proceder de la siguiente forma:
$Tamaño:=Size of array(ArrInt) ARRAY REAL(ArrReal;$Tamaño) `Establecer el mismo tamaño para el array Real que para el array Entero For($i;1;$Size) ArrReal{$i}:=ArrInt{$i} `Copiar cada elemento End for
Recuerde que no puede cambiar el número de dimensiones de un array durante el proceso. Si copia un array de una dimensión en un array de bidimensional, el compilador genera un mensaje de error.
SELECTION TO ARRAY, ARRAY TO SELECTION, DISTINCT VALUES, SELECTION RANGE TO ARRAY
De la misma forma para 4D en modo interpretado, estos cuatro comandos no necesitan la declaración de arrays. Los arrays no declarados reciben el mismo tipo que el campo especificado en el comando.
Si escribe:
SELECTION TO ARRAY([MiTabla]CampoEntero;MiArray)
el tipo de datos de MiArray sería Entero de una dimensión. (asumiendo que CampoEntero es un campo entero).
Si el array ha sido declarado, asegúrese de que el campo sea del mismo tipo. Aunque Entero, Entero largo y Real son tipos similares, no son equivalentes.
Por otra parte, en el caso de tipos Texto y Alfa, tiene un poco más de latitud. Por defecto, si un array no fue declarado previamente y usted aplica un comando que incluye un campo de tipo Alfa como parámetro, se atribuye el tipo Texto al array. Si el array fue declarado previamente como de tipo Alfa o de tipo Texto, estos comandos seguirán sus directivas.
Lo mismo ocurre en el caso de los campos de tipo Textosus directivas tienen prioridad.
Recuerde que los comandos SELECTION TO ARRAY, SELECTION RANGE TO ARRAY, ARRAY TO SELECTION y DISTINCT VALUES sólo pueden utilizarse con arrays de una dimensión.
El comando SELECTION TO ARRAY también tiene una segunda sintaxis:
SELECTION TO ARRAY(tabla;Array).
En este caso, la variable MiArray será de Array de Enteros largos. El comando SELECTION RANGE TO ARRAY funciona de la misma forma.
LIST TO ARRAY, ARRAY TO LIST
Los comandos LIST TO ARRAY y ARRAY TO LIST conciernen sólo a dos tipos de arrays:
los arrays Alfa de una dimensión y
los arrays Texto de una dimesnión.
Estos comandos no necesitan la declaración del array que se pasa como parámetro. Por defecto, un array no declarado recibirá el tipo Texto. Si el Array fue declarado previamente como de tipo Alfa o Texto, estos comandos seguirán sus directivas.
Utilización de punteros en comandos relacionados con arrays
El compilador no puede detectar un conflicto de tipo si usted utiliza un puntero sin referencia como parámetro de un comando de declaración de un array. Si escribe:
SELECTION TO ARRAY([Tabla]Campo;Puntero->)
donde Puntero-> representa un array, el compilador no puede verificar que el tipo del campo y el del array son idénticos. Usted debe prevenir tales conflictos; debe declarar el array referenciado por el puntero.
El compilador emite una advertencia cuando encuentra una rutina de declaración de array en la cual uno de los parámetros es un puntero. Estos mensajes pueden ser útiles en la detección de este tipo de conflicto.
Arrays locales
Si su base utiliza arrays locales (arrays reconocidos únicamente en el método en el que fueron creados), es necesario declararlos explícitamente en 4D antes de utilizarlos.
Para declarar un array local, utilice uno de los comandos de array tales como ARRAY REAL, ARRAY INTEGER, etc.
Por ejemplo, si un método crea un array local de enteros que contiene 10 elementos, debe declarar el array antes de utilizarlo. Utilice el comando:
ARRAY INTEGER($MiArray;10)
Lenguaje
Get pointer(varNombre)
Type (objeto)
EXECUTE FORMULA(instrucción)
TRACE
NO TRACE
Get pointer
Get pointer es una función que devuelve un puntero al parámetro que usted le pasó. Suponga que quiere inicializar un array de punteros. Cada elemento en ese array apunta a una variable dada. Suponga que hay doce variables llamadas V1, V2, V12. Puede escribir:
ARRAY POINTER(Arr;12) Arr{1}:=->V1 Arr{2}:=->V2 Arr{12}:=->V12
También puede escribir:
ARRAY POINTER(Arr;12) For($i;1;12) Arr{$i}:=Get pointer("V"+String($i)) End for
Al final de esta operación, puede obtener un array de punteros donde cada elemento apunta a una variable Vi.
Estas dos secuencias pueden compilarse. Sin embargo, si las variables V1 a V12 no se utilizan explícitamente en otra parte de la base, el compilador no puede darles un tipo. Por lo tanto, deben ser utilizadas o declaradas explícitamente en otra parte.
Esta declaración explícita puede realizarse de dos formas:
Declarando V1, V2, V12 a través de una directiva de compilación:
C_LONGINT(V1;V2;V3;V4;V5;V6;V7;V8;V9;V10;V11;V12)
Asignando estas variables en un método:
V1:=0 V2:=0 V12:=0
Type (objeto)
Como cada variable en una base compilada tiene un solo tipo, esta función puede parecer no muy útil. Sin embargo, puede ser útil cuando trabaja con punteros. Por ejemplo, puede ser necesario conocer el tipo de la variable a la cual el puntero hace referencia; debido a la flexibilidad de los punteros, no siempre es posible saber a que objeto apuntan.
EXECUTE FORMULA
Este comando ofrece ventajas en modo interpretado que no ofrece en modo compilado.
En modo compilado, un nombre de método pasado como parámetro a este comando será interpretado. Por lo tanto, usted no se beneficia de las ventajas ofrecidas por el compilador y la sintaxis de su parámetro no podrá verificarse.
Además, usted no puede pasar variables locales como parámetros.
Puede reemplazar EXECUTE FORMULA por una serie de instrucciones. Estos son dos ejemplos.
Dada la siguiente secuencia:
i:= FormFunc EXECUTE FORMULA("INPUT FORM (Form"+String(i)+")")
Puede reemplazarla por:
i:=FormFunc VarForm:="Form"+String(i) INPUT FORM(VarForm)
Miremos este otro ejemplo:
$Num:=SelPrinter EXECUTE FORMULA("Print"+$Num)
Acá, EXECUTE FORMULA puede reemplazarse por Case of:
Case of : ($Num=1) Print1 : ($Num=2) Print2 : ($Num=3) Print3 End case
El comando EXECUTE FORMULA puede reemplazarse siempre. Como el método a ejecutar se elije de la lista de los métodos de proyecto de la base o de los comandos de 4D, hay un número finito de métodos. Por lo tanto, siempre es posible reemplazar el comando EXECUTE FORMULA por Case of o por otro comando. Además, su código se ejecutará más rápido.
TRACE, NO TRACE
Estos dos comandos se utilizan en el proceso de depuración. No tienen ningún objetivo en una base compilada. Sin embargo, puede manterlos en sus métodos, simplemente serán ignorados por el compilador.
Variables
Undefined(variable)
SAVE VARIABLES(documento;variable1{; variable2 })
LOAD VARIABLES(documento;variable1{; variable2 })
CLEAR VARIABLE(variable)
Undefined
Teniendo en cuenta el proceso de declaración efectuado por el compilador, una variable no puede en ningún momento indefinida en modo compilado. De hecho, todas las variables han sido definidas en el momento en que termina la compilación. La función Undefined por lo tanto siempre devuelve False, sin importar el parámetro que se pase.
Nota: Para saber si su aplicación está corriendo en modo compilado, llame el comando Compiled application.
SAVE VARIABLES, LOAD VARIABLES
En modo interpretado, puede verificar que el documento existe probando si una de las variables está indefinida después de la ejecución de LOAD VARIABLES. Esto no es posible en bases compiladas, ya que la función Undefined siempre devuelve False.
Esta prueba puede realizarse en modo interpretado o compilado:
1. Inicialice las variables que va a recibir en un valor que no sea un valor legal para cualquiera de las variables.
2. Compare una de las variables recibidas con el valor de inicialización después de LOAD VARIABLES.
El método se puede escribir de este modo:
Var1:="xxxxxx" `"xxxxxx" es un valor que no puede ser devuelto por LOAD VARIABLES Var2:="xxxxxx" Var3:="xxxxxx" Var4:="xxxxxx" LOAD VARIABLES("Documento";Var1;Var2;Var3;Var4) If(Var1="xxxxxx") `Documento no encontrado Else `Documento encontrado End if
CLEAR VARIABLE
Esta rutina utiliza dos sintaxis diferentes en modo interpretado:
CLEAR VARIABLE(variable)
CLEAR VARIABLE("a")
En modo compilado, la primera sintaxis de CLEAR VARIABLE(variable) reinicializa la variable (puesta en cero para un numérico; cadena vacía para un cadena de caracteres o un texto, etc.), ya que ninguna variable puede estar indefinida en modo compilado.
Por lo tanto, CLEAR VARIABLE no libera memoria en modo compilado, excepto en cuatro casos: las variable de tipo Texto, Imagen, BLOB y Arrays.
Para un Array, CLEAR VARIABLE tiene el mismo efecto que una nueva declaración del array donde el tamaño se establece como cero.
Para un array MiArray cuyos elementos son de tipo Entero, CLEAR VARIABLE(MiArray) tiene el mismo efecto de una de las expresiones siguientes:
ARRAY INTEGER(MiArray;0) `si es un array de una dimensión ARRAY INTEGER(MiArray;0;0) `si es un array de dos dimensiones
La segunda sintaxis, CLEAR VARIABLE("a"), no es compatible con el compilador, ya que el compilador accede a las variables por dirección, no por nombre.
Punteros con ciertos comandos
Los siguientes comandos tienen una característica en común: aceptan un primer parámetro opcional [Tabla] y el segundo parámetro puede ser un puntero.
ADD TO SET | LOAD SET |
APPLY TO SELECTION | LOCKED ATTRIBUTES |
COPY NAMED SELECTION | ORDER BY |
CREATE EMPTY SET | ORDER BY FORMULA |
CREATE SET | OUTPUT FORM |
CUT NAMED SELECTION | PAGE SETUP |
DIALOG | Print form |
EXPORT DIF | PRINT LABEL |
EXPORT SYLK | QR REPORT |
EXPORT TEXT | QUERY |
GOTO RECORD | QUERY BY FORMULA |
GOTO SELECTED RECORD | QUERY SELECTION |
GRAPH TABLE | QUERY SELECTION BY FORMULA |
IMPORT DIF | REDUCE SELECTION |
IMPORT SYLK | RELATE MANY |
IMPORT TEXT | REMOVE FROM SET |
INPUT FORM |
En modo compilado, es fácil devolver el parámetro opcional [Tabla]. Sin embargo, cuando el primer parámetro pasado a uno de estos comandos es un puntero, el compilador no sabe a que puntero está haciendo referencia; el compilador lo trata como un puntero de tabla.
Tomemos el caso del comando QUERY cuya sintaxis es la siguiente:
QUERY({tabla{;formula{;*}})
El primer elemento del parámetro formula debe ser un campo.
Si escribe :
QUERY(PtrField->=True)
el compilador buscará un símbolo que represente un campo en el segundo elemento. Cuando encuentra el signo "=", emitirá un mensaje de error, al no poder identificar el comando con una expresión que sepa tratar.
Por otra parte, si escribe:
QUERY(PtrTabla->;PtrCampo->=True)
o
QUERY([Tabla];PtrCampo->=True)
evitará cualquier ambigüedad posible.
Constantes
Si crea sus propios recursos 4DK# (constantes), asegúrese de que los numéricos sean declarados como de tipo Entero largo (L) o Reales (R) y las cadenas de caracteres como Cadenas (S). Cualquier otro tipo generará una advertencia.
Ver también
Consejos de optimización , Guía de declaración, Mensajes de error , Utilización de directivas de compilación.