Eu me vi lutando para ver o que é esse princípio e por que é tão importante para o design da linguagem.
Basicamente, afirma que para cada expressão expr
na linguagem deve ser exatamente o mesmo que esta construção:
(function () { return expr; })()
Também ouvi dizer que Ruby obedece a esse princípio, enquanto Python não. Não entendo por que isso é verdade, ou se é verdade.
design
language-agnostic
Andrew
fonte
fonte
expr
obtém o rastreamento de pilha atual.Respostas:
Eu nunca tinha ouvido falar antes sobre o "Princípio da Correspondência de Tennent" e menos ainda sobre isso ser importante no design da linguagem. Pesquisando as expressões, parece que tudo leva a um blog de Neal Gafter, de 2006, que estabelece o que ele pensa que é e como ele acha que deve se aplicar aos fechamentos. E quase todos os outros nos fóruns parecem se referir à entrada de Gafter.
Aqui está, no entanto, uma menção do referido "TCP" por Douglas Crockford (um nome que eu conheço e confio): http://java.sys-con.com/node/793338/ . Em parte
Parece, portanto, que o nome "Princípio da Correspondência de Tennent" é mal utilizado, e tudo o que Neal fala possivelmente deve ser chamado de "TCP imaginado e possivelmente generalizado de Gafter" ... ou algo assim. De qualquer forma, não é o suficiente para se esconder atrás de uma cortina de nome de livro esgotada
fonte
Eu vejo isso como parte de uma regra geral de que uma linguagem bem projetada faz o que um programador naturalmente esperaria. Se eu tenho um bloco de código que quero refatorar em um fechamento e envolvo esse bloco com a sintaxe apropriada sem realmente pensar nas linhas de código individuais, espero que esse bloco faça a mesma coisa no fechamento como ele fez inline. Se algumas declarações usam a palavra-chave "this" (talvez implicitamente) e a linguagem faz com que "this" usado dentro do fechamento se refira a uma classe anônima usada para representá-lo, em vez da classe que define o método que define o fechamento, o significado de essas declarações foram alteradas, meu bloco de código não faz mais o que penso e preciso rastrear um bug e descobrir como alterar meu código para funcionar no fechamento.
O problema também pode ser mitigado com um IDE com ferramentas inteligentes de refatoração, que podem extrair fechamentos, detectar possíveis problemas e até ajustar automaticamente o código extraído para resolvê-los.
fonte
Claus Reinke: sobre o "Design da linguagem baseado em princípios semânticos" da Tennent
Dá uma interpretação interessante dos princípios:
"A correspondência é o princípio que nos permite dizer que
e
deve ser equivalente, e que qualquer coisa que possamos fazer em listas formais de parâmetros, também devemos poder fazer declarações e vice-versa. "[veja também Reinke, abaixo.]
RD Tennent: Métodos de design de linguagem baseados em princípios semânticos
"Dois métodos de design de linguagem baseados em princípios derivados da abordagem denotacional da semântica da linguagem de programação são descritos e ilustrados por uma aplicação no Pascal. Os princípios são, em primeiro lugar, a correspondência entre parâmetros paramétricos e mecanismos declarativos e, em segundo lugar, um princípio de abstração para linguagens de programação adaptadas da teoria dos conjuntos. Diversas extensões e generalizações úteis do Pascal emergem aplicando esses princípios, incluindo uma solução para o problema do parâmetro da matriz e um recurso de modularização ".
Claus Reinke: "Sobre programação funcional, design de linguagem e persistência" em Haskell
fonte
Para responder à pergunta por que o CP da Tennent é tão importante para o design de idiomas, gostaria de citar Neal Gafter :
Qualquer violação do TCP provavelmente prejudicará algum programador no futuro, quando ele espera que os fechamentos funcionem como código de não fechamento, mas descobre que, violando o TCP, eles não o fazem.
fonte
RE Python não segue este princípio. Geralmente, segue o princípio. Exemplo básico:
No entanto, o Python define expressões e instruções separadamente. Como
if
ramificações,while
loops, designações destrutivas e outras declarações não podem ser usadas emlambda
expressões, a letra do princípio de Tennent não se aplica a elas. Mesmo assim, restringir-se a usar apenas expressões Python ainda produz um sistema completo de Turing. Portanto, não vejo isso como uma violação do princípio; ou melhor, se violar o princípio, nenhuma linguagem que defina afirmações e expressões separadamente poderá estar em conformidade com o princípio.Além disso, se o corpo da
lambda
expressão estivesse capturando um rastreamento de pilha ou realizando outra introspecção na VM, isso poderia causar diferenças. Mas, na minha opinião, isso não deve ser considerado uma violação. Seexpr
e(lambda: expr)()
necessariamente compilar no mesmo bytecode, o princípio realmente diz respeito aos compiladores, não à semântica; mas se eles puderem compilar em diferentes códigos de bytes, não devemos esperar que o estado da VM seja idêntico em cada caso.Uma surpresa pode ser encontrada usando a sintaxe de compreensão, embora eu acredite que isso também não seja uma violação do princípio de Tennent. Exemplo:
A surpresa é o resultado de como as compreensões da lista são definidas. A compreensão "surpresa" acima é equivalente a este código:
Visto dessa maneira, a compreensão da "surpresa" acima é menos surpreendente, e não uma violação do princípio de Tennent.
fonte