Por que o operador de atribuição atribui o lado esquerdo?

47

Comecei a ensinar uma programação de amigos recentemente (estamos usando o Python), e quando começamos a discutir a criação de variáveis e o operador de atribuição, ela perguntou por que o valor à direita foi atribuído ao nome à esquerda, e não vice-versa.

Eu não tinha pensado muito nisso antes, porque parecia natural para mim, mas ela disse que a esquerda para a direita parecia mais natural para ela, já que é assim que a maioria de nós lê línguas naturais.

Pensei nisso e concluí que o código é muito mais fácil de ler, já que os nomes atribuídos (que o programador precisará reutilizar) são facilmente visíveis, alinhados à esquerda.

aligned = 2
on = 'foo' + 'bar' + 'foobar'
the = 5.0 / 2
left = 2 + 5

Em oposição a:

2 = aligned 
'foo' + 'bar' + 'foobar' = on
5.0 / 2 = the 
2 + 5 = right 

# What were the names again...?

Agora eu me pergunto se existem outras razões também para este padrão. Existe uma história por trás disso? Ou há alguma razão técnica pela qual essa é uma boa opção (não sei muito sobre compiladores)? E existem linguagens de programação que atribuem ao lado direito?

    
por voithos 04.08.2011 / 00:01
fonte

13 respostas

56

Ditto @paxdiablo. As primeiras linguagens de programação foram escritas por matemáticos - na verdade, todas elas eram. Na matemática, por seu próprio princípio - ler da esquerda para a direita - faz sentido no modo como funciona.

x = 2y - 4.

Na matemática, você diria isto: Seja x igual a 2y -4.

Além disso, mesmo em álgebra, você faz isso. Quando você resolve uma equação para uma variável, isola a variável que está resolvendo para o lado esquerdo. i.e. y = mx + b;

Além disso, uma vez que uma família inteira de idiomas - como a família C - tem uma certa sintaxe, é mais caro mudar.

    
por 04.08.2011 / 00:27
fonte
26

BASIC , uma das primeiras linguagens de computador tinha a forma "adequada" de:

10 LET AREA = HEIGHT * WIDTH

que corresponde à mentalidade matemática de especificar uma variável, como "Seja H a altura do objeto".

COBOL também foi semelhante com a declaração COMPUTE . Tal como acontece com muitas formas de fazer as coisas, pode ter sido simplesmente uma decisão arbitrária que foi levada adiante através de muitas línguas.

    
por 04.08.2011 / 00:16
fonte
25

Na verdade, existe uma linguagem de programação que atribui ao lado direito: TI-BASIC ! Não apenas isso, mas também não usa '=' como operador de atribuição, mas usa uma seta conhecida como operador "STO".

exemplos:

5→A
(A + 3)→B
(A - B)→C

No exemplo acima, três variáveis estão sendo declaradas e recebem valores. A seria 5, B seria 8 e C seria -3. A primeira declaração / atribuição pode ser lida 'loja 5 como A'.

Quanto ao motivo pelo qual a TI-BASIC usa um sistema desse tipo para atribuição, atribuo-a a ser porque é uma linguagem de programação para uma calculadora. O operador "STO" nas calculadoras TI era mais usado em operações normais da calculadora após um número foi calculado. Se fosse um número que o usuário quisesse lembrar, ele apertaria o botão "STO" e o gerenciador solicitaria um nome (ativando automaticamente o bloqueio alfabético para que as teclas produzissem letras em vez de números):

Sin(7 + Cos(3))
                    -.26979276
Ans→{variable name}
                    -.26979276

e o usuário poderia nomear a variável como quisesse. Ter que ativar o bloqueio alfabético, digitar o nome, pressionar "STO" e pressionar a tecla "Ans" teria sido complicado demais para as operações normais. Como todas as funções da calculadora estão disponíveis no TI-BASIC, nenhum outro operador de atribuição foi adicionado, já que "STO" executou a mesma tarefa, embora para trás, quando comparado à maioria dos outros idiomas.

(Anedota: TI-BASIC foi uma das primeiras línguas que aprendi, então quando eu estava aprendendo Java na faculdade, senti como se atribuir para o LEFT era incomum e 'para trás'!)

    
por 04.08.2011 / 06:51
fonte
15

Heurística 1: Quando se deparar com mais de uma maneira possível de fazer algo enquanto estiver projetando uma linguagem, escolha a mais comum e mais intuitiva, senão você terá Perl +.

Agora, como é mais natural (pelo menos para um falante de inglês)? Vamos ver como escrevemos / dizemos coisas em inglês:

Steven agora tem 10 anos (ao contrário de Steven, com 10 anos). Eu peso mais de 190 libras (ao contrário de mais de 190 libras eu peso).

no código:

steven = 10
i > 190

O seguinte também parece mais natural:

"Se Mary tem 18 anos, ela pode ter um doce". "Se eu tiver menos de 21 anos, pedirei ao meu irmão por tequila".

if (mary == 18) { ... }
if (i < 21) { ... }

do que:

"Se 18 anos, Mary é ..." "Se o 21 for maior que a minha idade ..."

Agora o código:

if (18 == mary) { ... }
if (21 > i) { ... }

Observe que isso não é natural nem para programadores nem para falantes de inglês. As frases soam como yoda-speak, e o código é apelidado de yoda-conditions. Isso pode ser útil em C ++, mas tenho certeza de que a maioria das pessoas concordaria: se um compilador pudesse fazer o trabalho pesado e aliviar a necessidade de condições de yoda, a vida seria um pouco mais fácil.

Claro, alguém poderia se acostumar com qualquer coisa. Para exemplos, o número 81 é escrito como:

oitenta e um (Inglês) Oitenta e um (espanhol) Um e oitenta (alemão).

Finalmente, existem 4! = 24 maneiras válidas de dizer "maçã verde encontra-se na mesa" em russo - a ordem (quase) não importa, exceto que 'on' deve vir junto com 'table'. Então, se você é um falante nativo de russo (por exemplo), então você pode não se importar se alguém escreve a = 10 ou 10 = a porque ambos parecem igualmente naturais.

Embora lingüística seja um assunto fascinante, eu nunca a estudei formalmente e não conheço muitas línguas. Espero ter fornecido contra-exemplos suficientes.

    
por 04.08.2011 / 03:58
fonte
11

Começou com o FORTRAN nos anos 50. Onde FORTRAN era uma abreviação de FORmula TRANslation - as fórmulas em questão são equações algébricas simples que por convenção sempre atribuem à esquerda.

Seu COBOL quase contemporâneo, por outro lado, deveria ser do tipo inglês e ser atribuído à direita (principalmente!).

MOVE 1 TO COUNTER.
ADD +1 TO LINE-CNT.
MULTIPLY QTY BY PRICE GIVING ITEM-PRICE.
    
por 04.08.2011 / 10:30
fonte
5

Bem, como apontou @diceguyd30, há duas notações.

  • <Identifier> = <Value> significa "let Identifier seja Valor ". Ou para expandir isso: Defina (ou redefina) a variável Identificador para Valor .
  • <Value> -> <Identifier> significa "armazenar Valor para Identificador ". Ou para expandir isso: Coloque Valor na localização designada por Identificador .

É claro que, em geral, o Identificador pode, de fato, ser qualquer valor-L.

A primeira abordagem respeita o conceito abstrato de variáveis, a segunda abordagem é mais sobre o armazenamento real.

Observe que a primeira abordagem também é comum em idiomas, que não possuem atribuições. Observe também que a definição e a atribuição de variáveis estão relativamente próximas de <Type> <Identifier> = <Value> vs. <Identifier> = <Value> .

    
por 04.08.2011 / 10:51
fonte
3

Como já foi mencionado, muito bem todas as primeiras linguagens de computador funcionaram dessa maneira. Por exemplo. FORTRAN, que surgiu muitos anos antes do BASIC.

Na verdade, faz muito sentido ter a variável designada à esquerda da expressão de atribuição. Em alguns idiomas, você pode ter várias rotinas sobrecarregadas diferentes com o SAME NAME, retornando diferentes tipos de resultados. Deixando o compilador ver primeiro o tipo da variável atribuída, ele sabe qual rotina sobrecarregada chamar, ou qual conversão implícita gerar ao converter (por exemplo) um inteiro para um float. Isso é uma explicação simplista, mas espero que você tenha a idéia.

    
por 04.08.2011 / 00:44
fonte
3

Poderia ser um remanescente de algoritmos de análise antecipada. Lembre-se que a análise LR só foi inventada em 1965, e pode muito bem ser que os analisadores LL tivessem problemas (dentro das limitações de tempo e espaço das máquinas na época), indo ao contrário. Considere:

identifier = function();
function();

Os dois estão claramente desambigurados do segundo símbolo. Por outro lado,

function() = identifier;
function();

Não é divertido. Isso fica pior quando você começa a aninhar expressões de atribuição.

function(prev_identifier = expression) = identifier;
function(prev_identifier = expression);

Claro, mais fácil de desambiguar para máquinas também significa mais fácil de desambiguar para os seres humanos. Outro exemplo fácil seria pesquisar a inicialização de qualquer identificador fornecido.

identifier1 = expressionOfAnArbitraryLength;
identifier2 = expressionOfAReallyReallyReallyArbitraryLength;
identifier3 = expression;
identifier4 = AlongLineExpressionWithAFunctionCallWithAssignment(
    identifier = expr);

Fácil, apenas olhe para o lado esquerdo. Lado direito, por outro lado

expressionOfAnArbitraryLength = identifier1;
expressionOfAReallyReallyReallyArbitraryLength = identifier2;
expression = identifier3;
AlongLineExpressionWithAFunctionCallWithAssignment(expr = identifier
    ) = identifier4;

Especialmente quando você não pode grep cartões perfurados, é muito mais difícil encontrar o identificador desejado.

    
por 05.08.2011 / 13:47
fonte
2

Idiomas de montagem têm o destino como parte do opcode do lado esquerdo. Linguagens de nível superior tendiam a seguir as convenções das linguagens predecessoras.

Quando você vê = (ou := para dialetos Pascalish), você pode pronunciá-los como is assigned the value , então a natureza da esquerda para a direita fará sentido (porque também lemos da esquerda para a direita em a maioria das línguas). Como as linguagens de programação eram predominantemente desenvolvidas por pessoas que liam da esquerda para a direita, as convenções se mantinham.

É um tipo de dependência de caminhos . Suponho que, se a programação de computadores fosse inventada por pessoas que falavam hebraico ou árabe (ou algum outro idioma da direita para a esquerda), então suspeito que estaríamos colocando o destino à direita.

    
por 04.08.2011 / 00:37
fonte
2

Por que vale a pena, a maioria das instruções em COBOL é lida da esquerda para a direita, então os dois operandos foram nomeados primeiro e o destino por último, como: multiply salary by rate giving tax .

No entanto, não vou sugerir que seu aluno prefira o COBOL, por medo de ser (bem justamente) marcado por fazer um comentário tão baixo, grosseiro e sem gosto! : -)

    
por 04.08.2011 / 22:22
fonte
1

she said that left-to-right seemed more natural to her, since that's how most of us read natural languages.

Eu acho que isso é um erro. Por um lado, você pode dizer "atribuir 10 a x" ou "mover 10 a x". Por outro lado, você pode dizer "set x a 10" ou "x torna-se 10".

Em outras palavras, dependendo da sua escolha de verbo, a variável designada pode ou não ser o assunto, e pode ou não estar à esquerda. Então, "o que é natural" depende inteiramente da sua escolha habitual de palavras para representar a atribuição.

    
por 05.08.2011 / 10:49
fonte
0

No pseudocódigo, o operador de atribuição é muito comumente escrito à direita. Por exemplo

2*sqrt(x)/(3+y) -> z

Em calculadoras Casio, mesmo variantes não programáveis, a variável de atribuição também é exibida à direita

A+2B → C

Na frente, a variável também está à direita

expression variable !

No x86, a sintaxe da Intel tem o destino à esquerda, mas a sintaxe do GAS reverte a ordem, causando confusão para muitas pessoas, especialmente em instruções relacionadas à ordem dos parâmetros, como subtração ou comparações. Estas instruções são as mesmas em dois dialetos diferentes

mov rax, rbx    ; Intel syntax
movq %rbx, %rax ; GAS syntax

Ambos movem o valor em rbx para rax. Nenhuma outra linguagem de montagem que conheço escreve o destino à direita como GAS.

Some platforms put the expression on the left and the variable on the right:

MOVE expression TO variable      COBOL
expression → variable            TI-BASIC, Casio BASIC
expression -> variable           BETA, R
put expression into variable     LiveCode

link

A maioria das linguagens atribui o valor à esquerda, uma das razões para facilitar o alinhamento dos operadores, facilitar a leitura e reconhecer a variável, já que os operadores de atribuição e as posições das variáveis não variam muito nas linhas, e é mais fácil para ler como "let variable be some value".

No entanto, algumas pessoas preferem dizer "mover valor x para y" e escrever a variável à direita.

    
por 05.11.2015 / 16:47
fonte
-1

Acho que segue um modo de pensar lógico.
Tem que haver uma caixa (variável) primeiro, então você coloca um objeto (valor) dentro dela. Você não coloca o objeto no ar e coloca uma caixa ao redor dele.

    
por 04.08.2011 / 05:21
fonte