O “with” em linguagens de programação

Em linguagens de programação, eu sempre preferi o estilo “quanto mais recursos, melhor” (desde que os recursos não entrem em conflito entre si; citando maus exemplos: todo o Perl e algumas partes do C++). Mas hoje descobri um bom exemplo onde o equilíbrio é uma solução melhor.

Quando eu programava em Delphi (para os desinformados: dialeto do Pascal), eu usava com muita freqüência o comando (statement) with. Por exemplo:

with Objeto.GetIsso('aaa').GetAquilo('bbb') do
begin
    Propriedade1 := 1;
    Propriedade2 := 2;
    Propriedade3 := 4;
end;

Muito útil para setar várias propriedades de um objeto de uma vez só (e isso acontecia freqüentemente). Eu pensava: “Delphi não é a minha linguagem favorita, mas este recurso é legal! Se fosse em C++, seria muito mais irritante escrever um código desse tipo”. Mas aí, programando em C++, esse problema não acontecia. Por quê?

Porque em C++ podemos declarar uma variável temporária do tipo ponteiro ou referência para evitar repetição:


Aquilo & a = objeto.get_isso("aaa").get_aquilo("bbb");
a.propriedade1 = 1;
a.propriedade2 = 2;
a.propriedade3 = 4;

Em JavaScript, é possível fazer tanto no estilo Pascal quanto no estilo C++, porém o estilo Pascal não é recomendado, por causa da natureza dinâmica da linguagem (with-statement-considered-harmful). Como propriedades podem ser adicionadas livremente aos objetos e variáveis globais podem ser criadas apenas com uma atribuição, é difícil saber o que vai acontecer num with em JavaScript. Se a propriedade existir no objeto no momento da execução, ela será usada. Senão, uma variável externa (global, por exemplo) será usada. Se propriedades forem adicionadas ou excluídas do objeto durante a execução, ou se houver um erro de digitação no nome de uma variável, imprevistos podem acontecer facilmente. Por isso tem gente que recomenda declarar uma var local com nome curto e usá-la para acessar os membros (o mesmo que eu mostrei em C++).

Mas então, por que o with é tão útil em Delphi? Por uma combinação de características da linguagem:

Primeiro, em Delphi as variáveis e os membros dos objetos precisam ser declarados previamente (como qualquer linguagem com tipos estáticos). Então, é mais fácil ver quais identificadores são os membros de um objeto, quais são variáveis locais e globais e quais são erros de digitação. Pode não ser trivial, mas a definição é fixa em tempo de compilação.

Segundo, em Delphi as variáveis só podem ser declaradas no começo das funções (pra piorar, sequer é possível declarar em blocos internos, como em C89). Então o truque usado em C++ e Javascript exigiria que você fosse ao começo da função declarar variáveis temporárias só pra isso. É um incômodo muito grande. O with é melhor.

Terceiro, no Pascal original não havia classes nem objetos, apenas records (que correspondem a structs em C). E os ponteiros que a linguagem oferecia só podiam ser usados para alocação dinâmica, não era possível obter o endereço de uma variável qualquer. Então a técnica da variável temporária exigiria uma cópia. Não dá!

Por tudo isso, o with funciona bem em Pascal, funciona mal em JavaScript, mas não faz falta; e também não faz falta em C++. Por essa diferença no estilo das linguagens, o with acaba sendo meio que um estorvo em JavaScript: não combina com o estilo da linguagem. Em Delphi, é possível até mesmo usar o with para evitar a declaração de uma nova variável, como no exemplo abaixo, onde um objeto é instanciado, operações são chamadas e sua memória é liberada, tudo sem nem dar um nome ao objeto! Como a declaração de uma variável é um incômodo e fica longe do local do uso, esse truque se torna bem interessante.


with TCoisa.Create do
try
    FazIsso;
    FazAquilo;
finally
    Free;
end;

É por isso quem nem todo recurso combina com qualquer linguagem… Quando há muitos recursos, eles podem interagir de forma confusa, serem redundantes, e complicados de usar. Quando uma linguagem tem falta em recursos, certas coisas só podem ser criadas à base de CTRL+C, CTRL+V ou com geradores de código… Há muitos exemplos das duas coisas…

Anúncios

3 pensamentos sobre “O “with” em linguagens de programação

  1. (continuando) Hmm… Acho que seu fosse criar uma linguagem de programação, ela acabaria não tendo o with, porque declarar variáveis seria muito mais prático do que em Pascal.

  2. Prefiro o message cascading do Smalltalk =D

    (objeto := AlgumaClasse new)
    fazIsso;
    fazAquilo;
    fazAlgumaOutraCoisa;
    fazMaisUmaCoisinha.

  3. E não é que ontem mesmo eu estava dando uma olhada na sintaxe do Smalltalk (na Wikipedia) só por curiosidade?
    Agora eu sei que variáveis são declaradas entre | e |… E tinha visto essa sintaxe de “cascading” também!

    O message cascading é bem legal. Esse tipo de coisa em geral funciona bem (e fica “elegante”) quando a sintaxe da linguagem é bem regular.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s