Apresentando as variáveis inline na linguagem Delphi - Zetta-Ømnis Soluções Tecnológicas
Criado: Terça, 13 de Novembro de 2018 às 20:30 Categoria: Artigos
Publicado: Quarta, 14 de Novembro de 2018 às 16:51 Categoria Pai: Addicted 2 Delphi!
Última Atualização: Sexta, 10 de Julho de 2020 às 17:24 Acessos: 5096
O texto a seguir é uma tradução (versão brasileira[1]) do original disponível no blog de Marco Cantù (Marco Tech Blog) em http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html.
A linguagem Delphi, no Delphi 10.3, teve uma mudança bastante significativa em seu núcleo, permitindo muito mais flexibilidade no tocante a declaração de variáveis locais, seu escopo e tempo de vida. Esta é uma mudança que quebra um princípio fundamental da Linguagem Pascal original, mas oferece um grande número de vantagens, reduzindo a quantidade de código em muitos casos.
O bloco de variáveis clássico
Desde o Turbo Pascal 1.0 até agora, seguindo as regras clássicas da Linguagem Pascal, toda declaração de variáveis locais tinha de ser feita em um bloco de variáveis escrito antes do início de uma função, procedimento ou método:
Declarando variáveis inline
A nova sintaxe de declaração de variáveis inline permite que você declare a variável diretamente em um bloco de código (permitindo também múltiplos símbolos como de costume):
Apesar desta parecer uma diferença pequena, quando comparada com o uso do bloco de variáveis clássico, existem vários efeitos colaterais bons desta forma de declaração que fazem das variáveis inline um recurso realmente valioso.
Inicializando variáveis inline
Uma mudança significativa em relação ao modelo clássico de declaração de variáveis locais é que a declaração e a inicialização de uma variável inline podem ser feitas em uma instrução simples, tal como pode ser feito com variáveis globais. Isso deixa as coisas mais legíveis e simples, quando comparado ao método clássico, onde a inicialização de todas as variáveis era feita no início de uma função, procedimento ou método:
Ainda, se o valor de uma variável estiver disponível apenas posteriormente no bloco de código, ao invés de configurar um valor inicial qualquer (como 0 ou nil) para só depois atribuir o valor real, você pode atrasar a declaração da variável até que você possa calcular um bom valor inicial para ela:
Em outras palavras, enquanto no passado todas as variáveis locais eram visíveis para todo o bloco de código da função, procedimento ou método, agora uma variável inline é visível apenas após a posição de sua declaração até o final deste bloco de código.
Escopo e tempo de vida de variáveis inline declaradas em blocos aninhados
A limitação de escopo é mais relevante para as variáveis inline, pois ele não se aplica a toda função, procedimento ou método, mas apenas ao bloco begin-end onde a variável inline aparece. Em outras palavras, o escopo de uma variável inline é limitado ao bloco onde ela foi declarada e ela não pode ser usada fora deste bloco. Não apenas o escopo é limitado ao bloco begin-end, mas também o tempo de vida da variável é limitado a este bloco. Uma variável de um tipo de dados gerenciado (como uma interface, string ou record gerenciado) será descartada ao final do bloco onde ela foi declarada, e não ao final da função, procedimento ou método.
ShowMessage (J.ToString); // ERRO DE COMPILAÇÃO: "Undeclared identifier: J"
// J e K não são acessíveis aqui
Como se pode observar no trecho de código anterior, uma variável declarada dentro de um bloco begin-end é visível apenas neste bloco específico e não após o fim dele (end). Após o final das instruções if, J e K não são mais visíveis.
Como foi mencionado anteriormente, o efeito do escopo não é limitado apenas a visibilidade. Uma variável gerenciada, como uma referência de interface ou record, será corretamente limpa no fim do bloco onde ela foi declarada, em vez de no final da função, procedimento ou método:
end; // Intf.Release e MRec.Destroy serão implicitamente chamados ao final do escopo
end; // nenhuma limpeza adicional!
Inferência (dedução) de tipos para variáveis inline
Outro enorme benefício das variáveis inline é que o compilador agora pode, em várias circunstâncias, deduzir o tipo de uma variável inline, apenas observando o tipo da expressão ou valor atribuído a ela:
O tipo da expressão à direita do operador de atribuição (:=) é analisado a fim de determinar o tipo da variável. Alguns dos tipos de dados são "expandidos" para um tipo maior, como no caso anterior onde o valor numérico 22 (um ShortInt) é expandido para um Integer. Como regra geral, se a expressão à direita de := é um tipo inteiro e menor que 32 bits, a variável será declarada como um inteiro de 32 bits. Você pode declarar uma variável inline com um tipo de forma explícita, caso precise de uma variável de tamanho específico.
Embora esse recurso possa economizar a digitação de algumas teclas a mais para uma variável Integer ou String, a dedução de tipo de variável torna-se muito mais interessante no caso de tipos complexos, como instâncias de tipos genéricos. No trecho de código a seguir, os tipos deduzidos são TDictionary para a variável MyDictionary e TPair, para a variável APair:
ShowMessage (APair.Value.ToString);
MyDictionary.Free;
Note que as variáveis inline também seguem a regra básica do "tudo que se cria, precisa ser destruído depois". Isso não mudou!
Constantes inline
Além das variáveis, você agora pode declarar uma constante de forma inline. Isso pode ser feito tanto para constantes tipadas como não tipadas e neste último caso, o tipo é deduzido (um recurso que já existia para constantes há muito tempo). A seguir um exemplo simples:
const M: Integer = (L + H) div 2; // identificador simples, com tipo explícito
const M = (L + H) div 2; // identificador simples, sem tipo explícito (será deduzido)
Loops "for" com declaração inline de variável de controle
Outra circunstância específica na qual você pode tirar vantagem das declarações de variáveis inline são o seu uso como variáveis de controle tanto em loops "for-to" clássicos como nos modernos loops "for-in":
Você pode simplificar ainda mais o código tirando vantagem da dedução de tipos:
Este é um caso no qual ter a variável inline com um escopo limitado é particularmente benéfico, como no exemplo a seguir: ao tentar usar a variável I fora do loop irá causar um erro de compilação (no passado apenas um aviso era emitido em alguns casos):
ShowMessage (I.ToString); // ERRO DE COMPILAÇÃO: Undeclared Identifier "I"
As declarações de variáveis inline com dedução de tipos e escopo local, trazem ar fresco para a linguagem Delphi. Embora a legibilidade do código-fonte Pascal continue sendo um princípio a ser preservado, foi importante modernizar a linguagem em seu núcleo, removendo um pouco da ferrugem (real ou percebida). No caso das variáveis inline, existem muitas vantagens ao sair do estilo de codificação tradicional, cujo valor é evidente.
Ainda assim você pode manter seu código como está e pedir a seus colegas desenvolvedores que sigam a declaração tradicional. Nada no código ou estilo existente está errado entretanto as declarações de variáveis inline oferecem novas oportunidades. Eu já tenho problemas para voltar para versões mais antigas do Delphi... Apenas dizendo.
1 O texto não é uma tradução "um para um". Palavras foram substituídas, removidas ou adicionadas a fim de garantir o pleno entendimento do texto por leitores lusófonos