IMHO vincular uma variável a outra variável ou expressão é um cenário muito comum em matemática. De fato, no começo, muitos estudantes acham que o operador de atribuição (=) é algum tipo de ligação. Mas na maioria dos idiomas, a ligação não é suportada como um recurso nativo. Em alguns idiomas como C #, a ligação é suportada em alguns casos, com algumas condições preenchidas.
Mas IMHO implementar isso como um recurso nativo foi tão simples quanto alterar o seguinte código -
int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;
para isso-
int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;
Ou seja, colocar a instrução de ligação como atribuições após cada instrução alterar os valores de qualquer variável contida na expressão no lado direito. Depois disso, será possível aparar instruções redundantes (ou otimização na montagem após a compilação).
Portanto, por que não é suportado nativamente na maioria dos idiomas. Especialmente na família C de idiomas?
Atualizar:
De opiniões diferentes, acho que devo definir essa "ligação" proposta com mais precisão -
- Esta é uma maneira de vincular. Somente soma é vinculada a a + b, não ao contrário.
- O escopo da ligação é local.
- Depois que a ligação é estabelecida, ela não pode ser alterada. Ou seja, uma vez que a soma é vinculada a a + b, a soma sempre será a + b.
Espero que a idéia esteja mais clara agora.
Atualização 2:
Eu só queria esse recurso de P # . Espero que esteja lá no futuro.
fonte
Respostas:
Você está confundindo programação com matemática. Nem mesmo a programação funcional é inteiramente matemática, embora empreste muitas idéias e as transforme em algo que possa ser executado e usado para programação. A programação imperativa (que inclui a maioria das linguagens inspiradas em C, com exceções notáveis como JavaScript e os adições mais recentes ao C #) não tem quase nada a ver com matemática, então por que essas variáveis devem se comportar como variáveis em matemática?
Você deve considerar que isso nem sempre é o que você deseja. Muitas pessoas são mordidas por fechamentos criados em loops especificamente porque os fechamentos mantêm a variável, e não uma cópia do seu valor em algum momento, ou seja,
for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }
cria dez fechamentos que retornam9
. Portanto, você precisa oferecer suporte para os dois lados - o que significa o dobro do custo no "orçamento de complexidade" e mais um operador. Possivelmente também incompabilidades entre código usando isso e código não usando isso, a menos que o sistema de tipos seja sofisticado o suficiente (mais complexidade!).Além disso, implementar isso de forma eficaz é muito difícil. A implementação ingênua adiciona uma sobrecarga constante a todas as atribuições, o que pode aumentar rapidamente em programas imperativos. Outras implementações podem atrasar as atualizações até que a variável seja lida, mas isso é significativamente mais complexo e ainda possui sobrecarga, mesmo quando a variável nunca é lida novamente. Um compilador suficientemente inteligente pode otimizar ambos, mas compiladores suficientemente inteligentes são raros e exigem muito esforço para serem criados (observe que nem sempre é tão simples quanto no seu exemplo, especialmente quando as variáveis têm amplo escopo e o multithreading entra em jogo!).
Note que a programação reativa é basicamente sobre isso (até onde eu sei), então ela existe. Simplesmente não é tão comum nas linguagens de programação tradicionais. E aposto que alguns dos problemas de implementação listados no parágrafo anterior foram resolvidos.
fonte
Ele se encaixa muito mal na maioria dos modelos de programação. Representaria um tipo de ação à distância completamente descontrolada, na qual seria possível destruir o valor de centenas ou milhares de variáveis e campos de objetos, fazendo uma única atribuição.
fonte
a
oub
, é preciso considerar seu impacto sobre cada lugar quesum
é usado, e cada lugar que você lêsum
, você precisa considerar o quea
eb
estão fazendo. Para casos não triviais, isso pode ser complicado, especialmente se a expressão real vinculada asum
puder mudar no tempo de execução.Você sabe, eu tenho essa sensação incômoda de que a programação reativa pode ser legal em um ambiente Web2.0. Por que o sentimento? Bem, eu tenho essa página que é basicamente uma tabela que muda o tempo todo em resposta aos eventos onClick da célula da tabela. E os cliques nas células geralmente significam alterar a classe de todas as células em uma coluna ou linha; e isso significa infinitas voltas de getRefToDiv () e similares para encontrar outras células relacionadas.
IOW, muitas das ~ 3000 linhas de JavaScript que escrevi não fazem nada além de localizar objetos. Talvez a programação reativa possa fazer tudo isso a baixo custo; e com uma enorme redução nas linhas de código.
O que vocês acham disso? Sim, percebo que minha tabela possui muitos recursos semelhantes a planilhas.
fonte
Eu acho que o que você está descrevendo é chamado de planilha:
... avaliando
B1
retornos 7.EDITAR
A linguagem C às vezes é chamada de "assembly portátil". É uma linguagem imperativa, enquanto planilhas etc. são linguagens declarativas. Dizer
B1=A1+1
e esperarB1
reavaliar quando você mudaA1
é definitivamente declarativo. Linguagens declarativas (das quais linguagens funcionais são um subconjunto) são geralmente consideradas linguagens de nível superior, porque estão mais distantes do funcionamento do hardware.Em uma nota relacionada, linguagens de automação como lógica ladder são tipicamente declarativas. Se você escrever um degrau de lógica que diz
output A = input B OR input C
que vai reavaliar essa afirmação constantemente eA
pode mudar sempre queB
ouC
muda. Outras linguagens de automação, como o diagrama de blocos de funções (com o qual você pode estar familiarizado se tiver usado o Simulink), também são declarativas e são executadas continuamente.Alguns equipamentos de automação (incorporados) são programados em C e, se for um sistema em tempo real, provavelmente possui um loop infinito que reexecuta a lógica repetidas vezes, semelhante à maneira como a lógica ladder é executada. Nesse caso, dentro do loop principal, você pode escrever:
... e como está sendo executado o tempo todo, torna-se declarativo.
A
será constantemente reavaliado.fonte
C, C ++, Objetivo-C:
Os blocos fornecem o recurso de encadernação que você está procurando.
No seu exemplo:
você está definindo
sum
a expressãoa + b
em um contexto em quea
eb
são variáveis existentes. Você pode fazer exatamente isso com um "bloco" (também conhecido como fechamento, também conhecido como expressão lambda) em C, C ++ ou Objective-C com as extensões da Apple (pdf):Isso define
sum
um bloco que retorna a soma de a e b. O__block
especificador de classe de armazenamento indica issoa
eb
pode ser alterado. Dado o exposto, podemos executar o seguinte código:e obtenha a saída:
A única diferença entre o uso de um bloco e a "ligação" que você propõe é o par vazio de parênteses
sum()
. A diferença entresum
esum()
é a diferença entre uma expressão e o resultado dessa expressão. Observe que, como nas funções, os parênteses não precisam estar vazios - os blocos podem receber parâmetros da mesma forma que as funções.fonte
C ++
Atualizado para ser genérico. Parametrizado nos tipos de retorno e entrada. Pode fornecer qualquer operação binária que satisfaça os tipos parametrizados. O código calcula o resultado sob demanda. Ele tenta não recalcular os resultados, se conseguir se safar. Retire isso se for indesejável (por causa de efeitos colaterais, porque os objetos contidos são grandes, por causa do que seja.)
fonte