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…

Vídeos sobre C++ e D

Fazia tempo que queria postar estes links pra uns vídeos que falam de recursos muito interessantes do C++0x e do D.

São longos, não vi tudo :-), mas parecem ser interessantes. Só faltou tempo de eu comentar o que é cada um deles, hehe. :-O Mas dêem uma olhada!

C++ :

http://video.google.com/videoplay?docid=2768126766555555011

http://video.google.com/videoplay?docid=5262479012306588324

D:

http://video.google.com/videoplay?docid=-7073020265668105471

http://www.nwcpp.org/Downloads/2007/AdvancedD/index.html (slides da apresentação)