Para os comandos que operam sobre strings, só a função Character code requer atenção especial. Em modo interpretado, pode passar indiferentemente uma string não vazia ou vazia a esta função. Em modo compilado, não pode passar uma string vazia. Se passa uma string vazia e o argumento passado a Character code é uma variável, o compilador não poderá detectar um erro na compilação.
Estes dois comandos são utilizados para escriever e receber variáveis enviadas ao disco. As variáveis são passadas como parâmetros a estes comandos.
O parâmetro que passa deve ser sempre do mesmo tipo. Suponha que deseja enviar uma lista de variáveis a um arquivo. Para eliminar o risco de mudar os tipos de dados involuntariamente, recomendamos especificar ao princípio da lista o tipo das variáveis enviadas. Desta forma, quando você recebe estas variáveis, sempre começará por obter um indicador. Depois, quando chama a RECEIVE VARIABLE, a transferência se maneja através de uma instrução Case of.
O compilador vê uma diferença entre as duas: Mod aplica a todos os tipos numéricos, enquanto o operador % aplica somente a Inteiros e Inteiros longos. Se o operando do operador % excede a faixa dos Inteiros longos, o resultado retornado provavelmente será errado.
O comando IDLEfoi adicionado à linguagem 4D para manejar exceções. Este comando deve ser utilizado quando utilize o comando ON EVENT CALL.
Este comando pode ser definido como uma diretriz de gestão de eventos. Só o kernel (núcleo) de 4D pode detectar um evento sistema (clique do mouse, atividade do teclado, etc.). Na maioria dos casos, as chamadas ao kernel são iniciadas pelo mesmo código compilado, de uma maneira transparente para o usuário.
Por outra parte, quando 4D está esperando tranquilamente por um evento, por exemplo em um loop de espera, é evidente que não haverá nenhuma chamada.
Utilize este comando só em métodos de projeto de lidar com erros. Este comando funciona exatamente como em 4D, exceto em um método que tenha sido chamado por um dos seguintes comandos: EXECUTE FORMULA, APPLY TO SELECTION e APPLY TO SUBSELECTION. Trate de evitar esta situação.
Sete comandos de 4D são utilizados pelo compilador para determinar o tipo de um array:
COPY ARRAY(fuente;destino) SELECTION TO ARRAY(campo;Array) ARRAY TO SELECTION(Array;campo) SELECTION RANGE TO ARRAY(início;fim;campo;Array) LIST TO ARRAY(lista;Array{; itemRefs}) ARRAY TO LIST(Array;lista{; itemRefs}) DISTINCT VALUES(campo;Array)
O comando COPY ARRAY aceita dois parâmetros de tipo Array. Se um dos parâmetros de array não foi declarado, o compilador determina o tipo do array não declarado segundo o tipo do declarado. Esta dedução é realizada nos dois casos seguintes:
O array declarado é o primeiro parâmetro. O compilador atribuiu o tipo do primeiro array ao segundo array.
O array declarado é o segundo parâmetro. Neste caso, o compilador atribuiu o tipo de dado do segundo array ao primeiro array.
Como o compilador é rigoroso com os tipos, COPY ARRAY só pode ser feito desde um array de um certo tipo a um array do mesmo tipo. Portanto, se deseja copiar um array de elementos cujos tipos são similares, ou seja, Inteiros, Inteiros longos e Reais, ou Texto e Alfas, ou Alfas de diferentes longitudes, tem que copiar os elementos um por um.
Imagine que deseja copiar elementos de um Array Inteiro a um Array Real. Pode agir da seguinte forma:
$Tamanho:=Size of array(ArrInt) ARRAY REAL(ArrReal;$Tamanho) `Estabelecer o mesmo tamanho para o array Real que para o array Inteiro For($i;1;$Size)
ArrReal{$i}:=ArrInt{$i} `Copiar cada elemento End for
Lembre que não pode mudar o número de dimensões de um array durante o processo. Se copiar um array de uma dimensão em um array bidimensional, o compilador gera uma mensagem de erro.
Com 4D em modo interpretado, estes quatro comandos não necessitam a declaração de arrays. Os arrays não declarados recebem o mesmo tipo que o campo especificado no comando. Se escreve:
SELECTION TO ARRAY([MinhaTabela]CampoInteiro;MeuArray)
o tipo de dados de MeuArray seria Inteiro de uma dimensão. (assumindo que CampoInteiro seja um campo inteiro).
Se o array foi declarado, tenha certeza de que o campo seja do mesmo tipo. Mesmo que Inteiro, Inteiro longo e Real são tipos similares, não são equivalentes. Por outro lado, no caso de tipos Texto e Alfa, tem um pouco mais de latitude. Por padrão, se um array não foi declarado previamente e você aplica um comando que inclui um campo de tipo Alfa como parâmetro, se atribui o tipo Texto ao array. Se o array foi declarado previamente como de tipo Alfa ou de tipo Texto, estes comandos seguirão suas diretrizes.
O comando SELECTION TO ARRAY também tem uma segunda sintaxe: SELECTION TO ARRAY(tabla;Array). Neste caso, a variável MeuArray será de Array de Inteiros longos. O comando SELECTION RANGE TO ARRAY funciona da mesma forma.
os arrays Texto de uma dimensão. Estes comandos não necessitam a declaração do array que se passa como parâmetro. Por padrão, um array não declarado receberá o tipo Texto. Se o Array foi declarado previamente como de tipo Alfa ou Texto, estes comandos seguirão suas diretrizes.
O compilador não pode detectar um conflito de tipo se utilizar um ponteiro sem referência como parâmetro de um comando de declaração de um array. Se escreve:
SELECTION TO ARRAY([Tabela]Campo;Ponteiro->)
onde Ponteiro-> representa um array, o compilador não pode verificar que o tipo do campo e o do array são idênticos. Deve prevenir tais conflitos; deve declarar o array referenciado pelo ponteiro.
O compilador emite uma advertência quando encontra uma rotina de declaração de array na qual um dos parâmetros é um ponteiro. Estas mensagens podem ser úteis na detecção de este tipo de conflito.
Se seu banco utiliza arrays locais (arrays reconhecidos unicamente no método no qual foram criados), é necessário declará-los explicitamente em 4D antes de utilizá-los.
Para declarar um array local, utilize um dos comandos de array tais como ARRAY REAL, ARRAY INTEGER, etc.
Por exemplo, se um método cria um array local de inteiros que contém 10 elementos, deve declarar o array antes de utilizá-lo. Utilize o comando:
Get pointer é uma função que devolve um ponteiro ao parâmetro que você lhe passou. Suponha que deseja inicializar um array de ponteiros. Cada elemento nesse array aponta a uma variável dada. Suponha que há doze variáveis chamadas V1, V2, …V12. Pode escrever:
Ao final desta operação, pode obter um array de ponteiros onde cada elemento aponta a uma variável Vi.
Estas duas sequências podem ser compiladas. Entretanto, se as variáveis V1 a V12 não são utilizadas explicitamente em outra parte do banco, o compilador não pode dar-lhes um tipo. Portanto, devem ser utilizadas ou declaradas explicitamente em outra parte. Esta declaração explícita pode ser realizada de duas formas:
Declarando V1, V2, …V12 através de uma diretiva de compilação:
Como cada variável em um banco compilado tem um só tipo, esta função pode parecer não muito útil. Entretanto, pode ser útil quando trabalha com ponteiros. Por exemplo, pode ser necessário conhecer o tipo da variável a qual o ponteiro faz referencia; devido à flexibilidade dos ponteiros, nem sempre é possível saber a que objeto apontam.
Este comando oferece janelas em modo interpretado que não oferece em modo compilado. Em modo compilado, um nome de método passado como parâmetro a este comando será interpretado. Portanto, não se beneficia das janelas oferecidas pelo compilador e a sintaxe de seu parâmetro não poderá ser verificada. Além disso, você não pode passar variáveis locais como parâmetros. Pode substituir EXECUTE FORMULA por uma série de instruções. Estes são dois exemplos.
Dada a seguinte sequência:
i:=FormFunc EXECUTE FORMULA("FORM SET INPUT(Form"+String(i)+")")
Pode ser substituída por:
i:=FormFunc VarForm:="Form"+String(i) FORM SET INPUT(VarForm)
Case of
:($Num=1) Print1
:($Num=2) Print2
:($Num=3) Print3 End case
O comando EXECUTE FORMULA pode ser substituído sempre. Como o método a executar se escolhe da lista dos métodos de projeto do banco ou dos comandos de 4D, há um número finito de métodos. Portanto, sempre é possível substituir o comando EXECUTE FORMULA por Case of ou por outro comando. Além disso, seu código se executará mais rápido.
Estes dois comandos são utilizados no processo de depuração. Não tem nenhum objetivo em um banco compilada. Entretanto, pode mantê-los em seus métodos, simplesmente serão ignorados pelo compilador.
Considerando o processo de declaração efetuado pelo compilador, uma variável não pode em nenhum momento indefinida em modo compilado. Na verdade, todas as variáveis foram definidas no momento em que termina a compilação. A função Undefined portanto sempre retorna False, sem importar o parâmetro que seja passado.
Nota: para saber se sua aplicação está correndo em modo compilado, chame o comando Compiled application.
Em modo interpretado, pode verificar que o documento existe provando se uma das variáveis está indefinida depois da execução de LOAD VARIABLES. Isto não é possível em bancos compilados, já que a função Undefined sempre retorna False.
Esta proba pode ser realizada em modo interpretado ou compilado: 1. Inicialize as variáveis que vai receber em um valor que não seja um valor legal para qualquer das variáveis. 2. Compare uma das variáveis recebidas com o valor de inicialização depois de LOAD VARIABLES. O método pode ser escrita deste modo:
Var1:="xxxxxx" `"xxxxxx" é um valor que não pode ser retornado por LOAD VARIABLES Var2:="xxxxxx" Var3:="xxxxxx" Var4:="xxxxxx" LOAD VARIABLES("Documento";Var1;Var2;Var3;Var4) If(Var1="xxxxxx") `Documento não encontrado
Esta rotina utiliza duas sintaxes diferentes em modo interpretado: CLEAR VARIABLE(variable) CLEAR VARIABLE("a") Em modo compilado, a primeira sintaxe de CLEAR VARIABLE(variable) reinicializa a variável (colocada em zero para um numérico; cadeia vazia para um string de caracteres ou um texto, etc.), já que nenhuma variável pode estar indefinida em modo compilado. Portanto, CLEAR VARIABLE não libera memória em modo compilado, exceto em quatro casos: as variáveis de tipo Texto, Imagem, BLOB e Arrays. Para um Array, CLEAR VARIABLE tem o mesmo efeito que uma nova declaração do array onde o tamanho se estabelece como zero.
Para um array MeuArray cujos elementos são de tipo Entero, CLEAR VARIABLE(MiArray) tem o mesmo efeito de uma das expressões seguintes:
ARRAY INTEGER(MiArray;0) `sim é um array de uma dimensão ARRAY INTEGER(MiArray;0;0) `sim é um array de duas dimensões
A segunda sintaxe, CLEAR VARIABLE("a"), não é compatível com o compilador, já que o compilador acessar as variáveis por direção, não por nome.
Em modo compilado, é fácil retornar o parâmetro opcional [Tabela]. Entretanto, quando o primeiro parâmetro passado a um desses comandos é um ponteiro, o compilador não sabe a que ponteiro está fazendo referência; o compilador o trata como um ponteiro de tabela.
Tomemos o caso do comando QUERY cuja sintaxe é a seguinte: QUERY({tabla{;formula{;*}}) O primeiro elemento do parâmetro formula deve ser um campo. Se escreve :
o compilador buscará um símbolo que represente um campo no segundo elemento. Quando encontra o signo "=", emitirá uma mensagem de erro, ao não poder identificar o comando com uma expressão que saiba como processar.
When using pointers, there is a particularity concerning commands where the first parameter [aTable] and second parameter are both optional. In this context, for internal reasons, the compiler does not allow a command that returns a pointer (for example Current form table) to be passed directly as a parameter (an error is generated).
This is the case, for example, of the FORM SCREENSHOT command. The following code works in interpreted mode but is rejected during compilation:
//triggers a compilation error FORM SCREENSHOT(Current form table->;$formName;$myPict)
In this case, you can just use an intermediate variable in order for this code to be validated by the compiler:
//equivalent compilable code C_POINTER($ptr) $ptr:=Current form table FORM SCREENSHOT($ptr->;$formName;$myPict)
Se criar seus próprios recursos 4DK# (constantes), tenha certeza de que os numéricos sejam declarados como de tipo Inteiro longo (L) ou Reais (R) e as cadeias de caracteres como Strings (S). Qualquer outro tipo gerará uma advertência.