Histórico da Página
...
Portuguese | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Blocos de CódigoBlocos de código são um conceito existente há muito tempo em linguagens xBase. Não como é algo que apareceu da noite para o dia, e sim uma evolução progressiva utilizando a combinação de muitos conceitos da linguagem para a sua implementação.
Primeiro LembreteO AdvPl é uma linguagem baseada em funções. Funções têm um valor de retorno. Assim como o operador de atribuição :=. Assim, ao invés de escrever: x := 10 // Atribui o valor 10 à variável chamada XPode-se escrever: // Atribui e então exibe o valor da variável XA expressão x:=10 é avaliada primeiro, e então seu resultado (o valor de X, que agora é 10) é passada para a função cValToChar() para a conversão para caracter e, em seguida, para a função Alert() para a exibição. Por causa desta regra de precedência é possível atribuir um valor a mais de uma varíavel ao mesmo tempo: Z := Y := X := 0 Por causa dessa regra, essa expressão é avaliada como se fosse escrita assim: Z := ( Y := (X := 0) ) Apesar do AdvPL avaliar expressões da esquerda para a direita, no caso de atribuições isso acontece ao contrário, da direita para a esquerda. O valor é atribuído à variável X, que retorna o valor para ser atribuído à variável Y e assim sucessivamente. Pode-se dizer que o zero foi "propagado através da expressão".Outras linguagens de programação de alto nível possuem recursos similares, conhecidos por "funções anônimas" ou "Lambda Functions". Um conteúdo do tipo Bloco de Código no AdvPL corresponde ao tipo de variável "B" (Block). Diferenças entre funções e Blocos de Código Uma função criada eu um código AdvPL pode ter nenhum, um ou mais parâmetros, e podem ou não ter um valor de retorno. E, no código dessa função, podemos escrever um programa complexo, usando outras funções, operadores, expressões e comandos da linguagem. Loops ( FOR ... NEXT, WHILE ... END ), desvios condicionais ( IF .. ELSEIF ... ELSE ... ENDIF / CASE ... END CASE ), enfim, tudo o que o AdvPL nos oferece. Um bloco de código é uma forma de criar uma função anônima, que pode receber ou não parâmetros, o código a ser executado pode ser uma expressão AdvPL, ou mais de uma expressão ( lista de expressões ), executadas sequencialmente. As expressões são limitadas a funções e operadores da linguagem, mas não permitem comandos... E, implicitamente, o retorno de uma execução de um Bloco de Código é sempre o resultado da expressão executada – e no caso de mais de uma instruçao, o retorno é o resultado da última expressão do bloco. Estrutura e declaração de um Bloco de Código { | [parametros,...] | [expressão,...] } Exemplo Didático entre Função e Bloco de Código Vamos partir de uma função simples, mostrando como ela pode ser escrita e usada como um bloco de código.
Essas mesmas operações podem ser escritas em um bloco de código , de apenas uma linha, que fará exatamente a mesma coisa que a função SomaAbs():
Utilizando Blocos de Código - Exemplo aSort()Blocos de código podem ser utilizados em diversas situações. Geralmente são utilizados para executar tarefas quando eventos de objetos são acionados. Por exemplo, considere a matriz abaixo: A := {"CARLA", "ANDREA", "BEATRIZ"}
{"ANDREA", "BEATRIZ", "CARLA"}
Outro LembreteEm AdvPL pode-se juntar diversas linhas de código em uma única linha física do arquivo. Por exemplo, o código: If lAchou Alert("Cliente encontrado!")pode ser escrito assim: If lAchou ; Alert("Cliente encontrado!") ; Endif O ponto-e-vírgula indica ao AdvPL que a nova linha de código está para começar. Pode-se então colocar diversas linhas lógicas de código na mesma linha física através do editor de texto utilizado. Apesar da possibilidade de se escrever todo o programa assim, em uma única linha física, isto não é recomendado pois dificulta a legibilidade do programa e, consequentemente, a manutenção.
Lista de ExpressõesA evolução dos blocos de código começa com as listas de expressões. Nos exemplos a seguir, o símbolo ==> indicará o retorno da expressão após sua avaliação (seja para atribuir em uma variável, exibir para o usuário ou imprimir em um relatório), que será impresso em um relatório por exemplo. Duas Linhas de Código @00,00 PSAY x := 10 ==> 10Cada uma das linhas terá a expressão avaliada, e o valor da variável será então impresso. Duas Linha de Código em uma , Utilizando Ponto-e-Vírgula Este é o mesmo código que o anterior, apenas escrito em uma única linha: Alert( cValToChar( x := 10 ; y := 20 ) ) ==> 10 Apesar desse código se encontrar em uma única linha física, existem duas linhas lógicas separadas pelo ponto-e-vírgula. Ou seja, esse código é equivalente a:Alert( cValToChar( x := 10 ) )Portanto, apenas o valor 10 da variável x será passado para as funções cValToChar() e Alert() para ser exibido. E o valor 20 apenas será atribuído à variável y.
Convertendo para uma Lista de ExpressõesQuando parênteses são colocados ao redor do código e o sinal de ponto-e-vírgula substituído por uma vírgula apenas, o código torna-se uma lista de expressões: Alert( cValToChar ( ( X := 10 , Y := 20 ) ) ) ==> 20 O valor de retorno resultante de uma lista de expressões é o valor resultante da última expressão ou elemento da lista. Funciona como se fosse um pequeno programa ou função, que retorna o resultado de sua última avaliação (efetuadas da esquerda para a direita).Neste exemplo, a expressão x := 10 é avaliada, e então a expressão y := 20, cujo valor resultante é passado para a função Alert() e cValToChar(), e então exibido. Depois que essa linha de código é executada, o valor de X é igual a 10 e o de y igual a 20, e 20 será exibido.Teoricamente, não há limitação para o número de expressões que podem ser combinadas em uma lista de expressões. Na prática, o número máximo é por volta de 500 símbolos.Debugar listas de expressões é difícil porque as expressões não estão divididas em linhas de código-fonte, o que torna todas as expressões associadas a uma mesma linha de código. Isto pode tornar muito difícil determinar onde um erro ocorreu.
Onde pode-se utilizar uma Lista de Expressões ?O propósito principal de uma lista de expressões é agrupá-las em uma única unidade. Em qualquer lugar do código AdvPL que uma expressão simples pode ser utilizada, pode-se utilizar uma lista de expressões. E ainda, pode-se fazer com que várias coisas aconteçam onde normalmente apenas uma aconteceria. X := 10 ; Y := 20Aqui temos o mesmo conceito, escrito utilizando listas de expressões na função iif: X := 10 ; Y := 20 De Listas de Expressões para Blocos de Código Considere a seguinte lista de expressões: Alert( cValToChar( ( x := 10, y := 20 ) ) ) ==> 20 O AdvPL permite criar funções, que são pequenos pedaços de código, como se fosse um pequeno programa, utilizados para diminuir partes de tarefas mais complexas e reaproveitar código em mais de um lugar num programa. Para mais detalhes, consulte a documentação sobre a criação de funções em AdvPL. Porém, a idéia neste momento é que a lista de expressões utilizada na linha anterior pode ser criada como uma função:Function Lista()E a linha de exemplo com a lista de expressões pode ser substituída, tendo o mesmo resultado, por: Alert( cValToChar( Lista() ) ) ==> 20 Como mencionado anteriormente, uma lista de expressões é como um pequeno programa ou função. Com poucas mudanças, uma lista de expressões pode se tornar um bloco de código:( X := 10 , Y := 20 ) // Lista de Expressões{|| X := 10 , Y := 20 } // Bloco de Código
Observe as chaves {} utilizadas no bloco de código. Ou seja, um bloco de código é uma matriz. Porém na verdade, não é uma lista de dados, e sim uma lista de comandos, uma lista de código. // Isto é uma matriz de dadosA := {10, 20, 30}
Executando um Bloco de CódigoDiferentemente de uma matriz, não se pode acessar elementos de um bloco de código através de um índice numérico. Porém blocos de código são semelhantes a uma lista de expressões, e a uma pequena função. Ou seja, podem ser executados. Para a execução, ou avaliação, de um bloco de código, deve-se utilizar a função EVal(): B := {|| x := 10, y := 20}Essa função recebe como parâmero um bloco de código e avalia todas as expressões contidas neste bloco de código, retornando o resultado da última expressão avaliada. ( O resultado de uma atribuição é o próprio conteúdo atribuído).
Passando ParâmetrosJá que blocos de código são como pequenas funções, também é possível a passagem de parâmetros para um bloco de código. Os parâmetros devem ser informados entre as barras verticais (||) separados por vírgulas, assim como em uma função. B := {| N | X := 10, Y := 20 + N} Porém, deve-se notar que já que o bloco de código recebe um parâmetro, um valor deve ser passado quando o bloco de código for avaliado.C := Eval(B, 1) ==> 21
Retorno de um bloco de códigoO retorno de um bloco de código será o resultado da última expressão avaliada dentro do bloco de código. Veja o exemplo abaixo : A = 0 Se a chamada do bloco de código informar o parâmetro 0 (zero), será retornado pelo bloco de código o retorno da função Time() do AdvPL. Ao ser chamado com um valor diferente de zero, será devolvido o retorno da função Date(), que retorna a data atual no servidor.
Utilizando Blocos de Código - Exemplo aSort()Blocos de código podem ser utilizados em diversas situações. Geralmente são utilizados para executar tarefas quando eventos de objetos são acionados. Por exemplo, considere a matriz abaixo: A := {"GARY HALL", "FRED SMITH", "TIM JONES"} Esta matriz pode ser ordenada pelo primeiro nome, utilizando-se a chamada da função ASort(A), resultando na matriz com os elementos ordenados dessa forma:{"FRED SMITH", "GARY HALL", "TIM JONES"} A ordem padrão para a função ASort é ascendente. Este comportamento pode ser modificado através da informação de um bloco de código que ordena a matriz de forma descendente:B := { |X, Y| X > Y } O bloco de código utilizado neste exemplo (de acordo com a documentação da função ASort()) deve ser escrito para aceitar dois parâmetros, que são os dois elementos da matriz para comparação. Observe que o bloco de código não conhece que elemento está comparando - a função aSort() seleciona os elementos e passa-os para o bloco de código. O bloco de código compara-os e retorna verdadeiro (.T.) se encontram na ordem correta, caso contrário retorna falso (.F.). A função ASort() executará quantas chamadas forem necessárias para ordenar o array até que a sequência de elementos esteja devidamente ordenada.Para ordenar a mesma matriz pelo último nome, também em ordem decrescente, pode-se utilizar o seguinte bloco de código: B := { |X, Y| Substr(X,At(" ",X)+1) > Substr(Y,At(" ",Y)+1) } Observe que este bloco de código procura e compara as partes dos caracteres imediatamente seguinte a um espaço em branco. Depois de utilizar esse bloco de código para a função ASort, a matriz estará na seguinte ordenação:, Y| X > Y }
{"GARY HALL", "TIM JONES", "FRED SMITH"}
Utilização Avançada de Blocos de CódigoÉ possivel criar um bloco de código dinamicamente no AdvPL, utilizando-se do operador de macro-execução, bem como chamar de dentro de um bloco de código qualquer função da linguagem AdvPL e funções compiladas no repositório. Estes recursos possuem algumas particularidades de uso, exploradas nos exemplos abaixo. Exemplo 01 : Bloco de código referenciando variável local
ReturnSTATIC
Antes: 0 5
Exemplo 02 : Bloco de código com parâmetros por referência
ReturnUser
Dicas Importantes/Informações Adicionaisna variável original usada na chamada da função. Esta mesma regra é válida para um bloco de código, onde podemos passar por referência um ou mais parâmetros na chamada da função Eval(), reproduzindo o mesmo comportamento. Dicas Importantes / Informações Adicionais / Boas Práticas
|