ti-enxame.com

É um design ruim para uma linguagem de programação permitir espaços nos identificadores?

Algumas linguagens de programação ( link 1 , link 2 ) permitem espaços em seus identificadores (por exemplo, variáveis, procedimentos), mas a maioria delas não e, em vez disso, os programadores geralmente usam caso camelo , caso cobra e outras maneiras de separar palavras em nomes.

Para suportar espaços ou até outros caracteres Unicode, algumas linguagens de programação permitem encapsular o nome com um determinado caractere para delimitar seu início e fim.

É uma má idéia permitir espaços ou geralmente não é permitido por razões históricas (quando havia mais limitações do que agora ou simplesmente sendo decidido que não vale a pena implementar)?

A questão é mais sobre os principais prós e contras de implementá-lo em linguagens de programação recém-criadas.

Páginas relacionadas: link 1 , link 2 .

51
user7393973

Considere o seguinte.

 var [Example Number] = 5;
 [Example Number] = [Example Number] + 5;
 print([Example Number]);

 int[] [Examples Array] = new int[25];
 [Examples Array][[Example Number]] = [Example Number]

Compare-o com o exemplo mais tradicional:

 var ExampleNumber = 5;
 ExampleNumber = ExampleNumber + 5;
 print(ExampleNumber);

 int[] ExamplesArray = new int[25];
 ExamplesArray[ExampleNumber] = ExampleNumber;

Tenho certeza de que você notou que a tensão do seu cérebro para ler o segundo exemplo era muito menor.

Se você permitir espaços em branco em um identificador, precisará colocar outro elemento de idioma para marcar o início e a parada de uma palavra. Esses delimitadores forçam o cérebro a fazer uma análise extra e, dependendo de qual você escolher, cria um novo conjunto de questões de ambiguidade para o cérebro humano.

Se você não colocar delimitadores e tentar inferir de que identificador está falando ao digitar código apenas por contexto, convide outro tipo de lata de worms:

 var Example = 5;
 var Number = 10;
 var Example Number = Example + Number;

 int[] Examples Array = new int[25];
 Examples Array[Example Number] = Example Number;

 Example Number = Example Number + Example + Number;
 print text(Example Number);

Perfeitamente factível.

Uma dor total para a correspondência de padrões do seu cérebro.

Esses exemplos são difíceis de ler, não apenas por causa da escolha das palavras que estou escolhendo, mas também porque seu cérebro leva mais tempo para identificar o que é todo identificador.

Considere o formato mais regular, mais uma vez:

 var Example = 5;
 var Number = 10;
 var ExampleNumber = Example + Number;

 int[] ExamplesArray = new int[25];
 ExamplesArray[ExampleNumber] = ExampleNumber;

 ExampleNumber = ExampleNumber + Example + Number;
 printText(ExampleNumber);

Você percebe alguma coisa?

Os nomes das variáveis ​​ainda são terríveis, mas a pressão para lê-lo diminuiu bastante. Isso acontece porque seu cérebro agora tem uma âncora natural para identificar o início e o fim de cada Palavra, permitindo que você abstraia essa parte do seu pensamento. Você não precisa mais se preocupar com esse contexto - você vê uma quebra no texto, sabe que é um novo identificador chegando.

Ao ler o código, seu cérebro não lê muito as palavras tanto quanto corresponde com o que você tem em mente agora. Você realmente não para para ler "ExampleWord". Você vê a forma geral da coisa, ExxxxxxWxxd, a combina com o que você escondeu na sua pilha mental, e elas continuam lendo. É por isso que é fácil perder erros como "ExampleWord = ExapmleWord" - seu cérebro não está realmente lendo. Você está apenas combinando coisas semelhantes.

Mais uma vez, considere o seguinte:

 Example Word += Example  Word + 1;

Agora imagine-se tentando depurar esse código. Imagine quantas vezes você perderá esse espaço extra na "Palavra do Exemplo". Uma carta mal colocada já é difícil como garfo para detectar à primeira vista; um espaço extra é uma ordem de magnitude pior.

No final, é difícil dizer que permitir espaços em branco tornaria o texto mais legível. Acho difícil acreditar que o incômodo adicional de terminadores extras e a sobrecarga extra em meu cérebro valham a pena usar esse tipo de funcionalidade se a linguagem com a qual estou trabalhando o tiver.

Pessoalmente, considero o design ruim - não por causa do incômodo no compilador, intérprete ou qualquer outra coisa, mas porque meu cérebro tropeça nesses espaços pensando que é um novo identificador que está prestes a começar, quando não está.

Em certo sentido, nosso cérebro sofre os mesmos problemas que nossos processadores, quando se trata de previsão de ramificação .

Então, por favor, seja gentil com nossas linhas de pensamento. Não coloque espaços em branco nos seus identificadores.

101
T. Sar

É um design ruim para uma linguagem de programação permitir espaços nos identificadores?

Resposta curta:

Talvez.

Resposta ligeiramente mais longa:

O design é o processo de identificar e ponderar soluções conflitantes para problemas complexos e fazer bons compromissos que atendem às necessidades das partes interessadas. Não existe "design incorreto" ou "design inadequado", exceto no contexto dos objetivos dessas partes interessadas , e você não disse quais são esses objetivos , então a pergunta é muito vaga para responder.

Resposta ainda mais longa:

Como aludi acima, depende dos objetivos do círculo eleitoral que o designer de idiomas está abordando. Vamos considerar duas linguagens que eu conheço: a forma legível para humanos do MSIL, a "linguagem intermediária" de baixo nível que o C # compila e o C #.

O C # deve ser uma linguagem que torne os desenvolvedores de linha de negócios altamente produtivos em ambientes que a Microsoft considera estrategicamente importantes. Em C #, um identificador é uma sequência de um ou mais caracteres UTF-16 em que todos os caracteres são classificados como alfanuméricos ou _, e o primeiro caractere não é um número.

Essa gramática lexical foi cuidadosamente escolhida para ter características que correspondam às necessidades daqueles desenvolvedores de LOB estrategicamente importantes:

  • É inequivocamente flexível como um identificador; 1e10 por exemplo, não deve ser um identificador legal porque é lexicamente ambíguo com um duplo.
  • Ele suporta expressões comuns usadas em C, C++ e Java, como nomear um campo privado _foo. O C # foi projetado para atrair desenvolvedores que já conheciam uma linguagem LOB comum.
  • Ele suporta identificadores escritos em quase qualquer idioma humano. Você quer escrever var φωτογραφία = @"C:\Photos"; em C #, você segue em frente. Isso torna o idioma mais acessível para desenvolvedores que não são falantes nativos de inglês.

No entanto, o C # não suporta espaços nos identificadores.

  • Isso complicaria a gramática lexical e introduziria ambiguidades que devem ser resolvidas.
  • Na grande maioria das situações de interoperabilidade, isso não é necessário. Ninguém nomeia seus membros públicos para ter espaços neles.

Foi uma boa idéia desabilitar caracteres que não sejam letras e números nos identificadores de C #.

No MSIL, por outro lado, você pode nomear uma função quase qualquer coisa, incluindo colocar espaços ou outros caracteres "estranhos" nos nomes dos métodos. E, de fato, o compilador C # tira proveito disso! Ele irá gerar "nomes indizíveis" para métodos gerados pelo compilador que não devem ser chamados diretamente pelo código do usuário.

Por que essa é uma boa idéia para o MSIL e não para o C #? Como os casos de uso do MSIL são completamente diferentes:

  • O MSIL não foi projetado como uma linguagem primária de desenvolvimento; Como é uma linguagem intermediária, o principal caso de uso é para desenvolvedores de compiladores que tentam entender a saída de seu compilador.
  • O MSIL foi projetado para poder interoperar com qualquer ambiente de desenvolvimento da Microsoft herdado, incluindo o Visual Basic anterior ao .NET e outros OLE = Clientes de automação, que permitiam espaços nos identificadores.
  • Como observado acima, ser capaz de gerar um nome "indizível" para uma função é um recurso, não um bug.

Então, é uma boa ideia permitir espaços nos identificadores? Depende dos casos de uso do idioma. Se você tiver um caso de uso sólido para permitir isso, permita-o. Se não, não.

Leitura adicional: Se você quiser um exemplo de uma linguagem fascinante que faça excelente uso de identificadores complexos, consulte Inform7 , um DSL para jogos de aventura baseados em texto:

The Open Plain is a room. 
"A wide-open grassy expanse, from which you could really go any way at all."

Isso declara um novo objeto do tipo room chamado The Open Plain, e esse objeto pode ser referido como tal durante todo o programa. O Inform7 possui um analisador muito rico e complexo, como você pode imaginar.

Aqui está um exemplo mais complexo:

Before going a direction (called way) when a room (called next location) is not visited:
  let further place be the room the way from the location;
  if further place is a room, continue the action;
  change the way exit of the location to the next location;
  let reverse be the opposite of the way;
  change the reverse exit of the next location to the location.

Observe que way e next location e further place e reverse são identificadores neste idioma. Observe também que next location e the next location estão com alias. (Exercício : o que esse código está fazendo com a estrutura de dados que mantém o mapa das salas no jogo?)

O Inform7 tem um grupo constituinte que deseja o idioma inglês completo como o código-fonte. Parece estranho escrever este Inform7 como

  change the way exit of the location to the_next_location;

É uma quebra de imersão fazer isso. Compare isso com a resposta (excelente) de T. Sar, que faz o ponto de contraste - que é imerso para desenvolvedores em linguagens LOB tentarem analisar mentalmente onde estão os identificadores. Novamente, tudo se resume ao contexto e às metas.

59
Eric Lippert

Um relativamente conhecido exemplo é de algum código Fortran no qual um único erro de digitação mudou completamente o significado do código.

Pretendia-se repetir uma seção do código 100 vezes (com I como contador de loop):

DO 10 I = 1,100

No entanto, a vírgula foi digitada incorretamente como um ponto:

DO 10 I = 1.100

Como o Fortran permite espaços nos identificadores (e porque cria variáveis ​​automaticamente, se não tiverem sido declaradas), a segunda linha é perfeitamente válida: cria implicitamente uma variável real espúria chamada DO10I e atribui o número 1.1. Portanto, o programa foi compilado sem erros; apenas falhou ao executar o loop.

O código em questão controlava um foguete; como você pode imaginar, esse tipo de erro poderia ter sido catastrófico! Felizmente, neste caso, o erro foi detectado nos testes e nenhuma nave espacial foi prejudicada.

Eu acho que isso mostra muito bem um dos perigos em permitir espaços nos identificadores ...

15
gidds

É um design ruim para uma linguagem de programação permitir espaços nos identificadores?

Você esqueceu detalhes importantes da implementação:

o que é código fonte para você?

Eu gosto da definição FSF : a forma preferida na qual os desenvolvedores trabalham. É uma definição social, não técnica.

Em alguns idiomas e na implementação dos anos 80 (pense nas máquinas originais Smalltalk e Smalltalk de 1980), o código-fonte não era uma sequência de caracteres. Era uma árvore de sintaxe abstrata e foi manipulada pelo usuário, com o mouse e o teclado, usando alguma GUI.

Em certo sentido, LISP comum aceita espaços em seus símbolos.

Você pode decidir (isto é, lote do trabalho) co-projetar a sua linguagem de programação ( documentada em algum relatório, fornecendo sintaxe e semântica ), sua implementação (como alguns softwares) e seu editor ou IDE (como alguns softwares).

Leia discussões antigas em tunes.org . Leia o antigo trabalho do INRIA em

@TechReport{Jacobs:1992:Centaur,
 author =       {Jacobs, Ian and Rideau-Gallot, Laurence},
 title =        {a {\textsc{Centaur}} Tutorial},
 institution =  {\textsc{Inria} Sophia-Antipolis},
 year =         1992,
 number =       {RT-140},
 month =        {july},
 url =          {ftp://www.inria.fr/pub/rapports/RT-140.ps}
}

e

@techreport{donzeaugouge:inria-mentor,
 TITLE =        {{Programming environments based on structured
                 editors : the \textsc{Mentor} experience}},
 AUTHOR =       {Donzeau-Gouge, Véronique and Huet, Gérard and Lang,
                 Bernard and Kahn, Gilles},
 URL =          {https://hal.inria.fr/inria-00076535},
 TYPE =         {Research Report},
 NUMBER =       {RR-0026},
 INSTITUTION =  {{INRIA}},
 YEAR =         1980,
 PDF =
              {https://hal.inria.fr/inria-00076535/file/RR-0026.pdf},
 HAL_ID =       {inria-00076535},
 HAL_VERSION =  {v1},
}

Veja também meu relatório preliminar do Bismon e http://refpersys.org/

Meu sonho com o RefPerSys é co-projetar uma linguagem de programação declarativa com um Nice IDE para isso. Sei que pode levar uma década. Sinta-se à vontade para pensar que somos loucos, em certo sentido) estamos!

Do ponto de vista da usabilidade, coloração de sintaxe e preenchimento automático é mais importante que os espaços nos identificadores (observe os GtkSourceView e CodeMirror para inspiração). Visualmente um sublinhado _ parece próximo a um caractere de espaço. E se você codificar seu próprio IDE, poderá aceitar ctrlspace como entrada para "espaços dentro de nomes". Minha opinião é que ℕ e ∀ devem ser "palavras-chave", a questão é como você as digita. Estou sonhando em digitar (inspirado no LaTeX) \forallESC para obter um ∀ (e eu ouvi falar de alguns emacs submodo para isso).

NB: Eu odeio Python (e Makefile - s)) porque os espaços em branco (ou tabulações) são significativos lá.

8
Basile Starynkevitch

Não é um design inerentemente ruim = permitir espaços nos nomes dos símbolos. Isso pode ser mostrado com um simples contra-exemplo.

Kotlin permite espaços em nomes. Ele também possui convenções oficiais de codificação que afirmam quando é permitido usar esse recurso :

Nomes para métodos de teste

Nos testes (e somente nos testes), é aceitável usar nomes de métodos com espaços entre backticks.

Exemplo:

class MyTestCase {
     @Test fun `ensure everything works`() { /*...*/ }

É claro que "bom" e "ruim" são subjetivos, mas o uso de espaços nos nomes dos métodos de teste torna o código de teste muito mais agradável de ler e também testa resultados Agradável de ler, sem que o codificador de teste precise se repetir com um nome de método feio e uma descrição do teste legível por humanos separadamente.

O ponto importante aqui é que esses métodos normalmente não serão chamados explicitamente a partir do código escrito por seres humanos, portanto, apenas o local onde o nome aparece está na definição do método. Eu acho que essa é uma distinção importante para considerar quando os espaços podem ser uma boa idéia nos nomes dos símbolos: somente quando o símbolo for escrito apenas uma vez pelo programador.

6
hyde

Regra prática:

Os erros são proporcionais ao tempo que leva para ler o código em voz alta.

Qualquer coisa que aumente o número de colchetes abertos, colchetes fechados, colchetes abertos, colchetes fechados, parênteses abertos, parênteses próximos ... aumentará o número de erros no código.

Essa é uma das razões pelas quais * é estrela ou splat, e não asterisco. # é shhh! é estrondo. Eu acho que matemáticos também têm expressões verbais curtas para seus símbolos.

É por isso que os campos de tecnologia se enchem de siglas e abreviações: pensamos em palavras. Temos um tempo de atenção finito e podemos conter apenas tantos símbolos em nossa cabeça. Então, agrupamos e agrupamos as coisas.

ReallyReallyLongIdentifier pode fazer a mesma coisa. Aí está a troca entre lembrar para que serve e nos envolver em nossos processos de pensamento. Mas ReallyReallyLongIndentifer ainda é melhor que QzslkjfZslk19

Quanto mais longe a criação é usada, mais precisa ser memorável. Assim, i, j, k é usado para construções de loop - como as libélulas vivem pela vida de um loop, e esse loop começa e termina na mesma tela.

Isso também se estende à codificação:

A = FunctionAlpha (21, $ C, $ Q)

B = FunctionBeta ($ A, $ D, $ R)

é mais limpo que

B = FunctionBeta (FunctionAlpha (21, $ C, $ Q), $ D, $ R)

Penso que esta é uma das razões pelas quais as planilhas têm taxas de erro tão péssimas: com exceção de células/linhas/colunas temporárias, não há como evitar declarações aninhadas e confusas.

3
Sherwood Botsford

Levei muito tempo para entender que nunca haverá realmente uma melhor linguagem. Para uma equipe de programação, os aspectos mais importantes são que a linguagem seja bem conhecida, suportada por muitas ferramentas, tenha uma sintaxe mínima da linguagem e surpreenda você o mais raramente possível.

Para um único codificador, é ótima uma linguagem poderosa que permite ciclos rápidos de teste/execução.

Para um administrador, um idioma adaptado ao idioma do Shell do sistema operacional é crítico.

Para algumas linguagens de trabalho compartilhadas entre as disciplinas, as DSLs podem ser agradáveis.

Existe um lugar para uma linguagem com espaços - provavelmente. Ele viola as regras não surpreendentes, mas se encaixa muito bem com os objetivos da DSL.

Uma coisa que acho que ninguém mencionou - com um costume [IDE] _ você pode realmente ter um espaço rígido e um espaço flexível. Eles pareceriam semelhantes (talvez tenham tons diferentes no IDE).

Nesse caso, você pode fazer isso agora com qualquer idioma - basta alternar entre IDE para que os sublinhados sejam exibidos como espaços. Qualquer um que cria plugins do Eclipse provavelmente poderá fazer isso em uma hora.

Também é possível converter pragmaticamente a caixa de camelo em "palavras com espaços", seu IDE poderia fazer isso por você, mas seria um pouco mais estranho.

0
Bill K