No -calculus, podemos codificar aritmética, números, booleanos e até calcular fatoriais de números, como mostrado aqui .
Existe codificação de "for" ou "while"?
No -calculus, podemos codificar aritmética, números, booleanos e até calcular fatoriais de números, como mostrado aqui .
Existe codificação de "for" ou "while"?
Respostas:
Certo! Deixe-me mostrar como codificar FOR usando um exemplo.
Suponha que desejemos traduzir um fator FOR simples para o programa
x := 1
for i := 1 to N do
x := x * i
Reescrevemos como
x := 1
i := 1
repeat N times
x := x*i
i := i+1
então colocamos todas as variáveis que usamos em uma tupla (um par é suficiente, aqui)
(x,i) := (1,1)
repeat N times
(x,i) := (x*i, i+1)
Isso efetivamente aplica a função para o par inicial por vezes.
Como pode ser representado como um numeral da Igreja, obtemos
A sintaxe acima usa algumas coisas além do cálculo lambda simples. Números e aritmética podem ser feitos com precisão usando números da Igreja. Os pares também têm sua própria codificação da Igreja:
Se você tiver mais de duas variáveis, poderá generalizar a codificação acima para tuplas ou simplesmente representar tuplas como pares aninhados.
QUANDO é melhor lidar com o uso de recursão: em vez de
while p(x,i) do
(x,i) := f(x,i)
Onde p
é um predicado e f
é uma função (parcial), podemos usar algo como
def recFun(x,i):
if p(x,i):
return recFun(f(x,i))
else:
return (x,i)
No cálculo lambda, a recursão é obtida usando um combinador de ponto fixo , por exemplo, da Igreja ou Turing . Temos algo como
onde supor que os booleanos sejam codificados pela Igreja.
Observe também que WHILE é (estritamente) mais poderoso que FOR. Todo FOR pode ser codificado como WHILE, portanto, essa técnica de codificação também pode ser usada para FOR.
Existem codificações de loops, mas elas não funcionam exatamente como os loops com os quais você está acostumado, porque o cálculo lambda não é uma linguagem imperativa. O cálculo lambda não tem efeitos colaterais (é uma linguagem puramente funcional ); portanto, o equivalente exato de um loop seria inútil.
Um programa imperativo pode ser traduzido para uma linguagem puramente funcional, passando todo o estado explicitamente como uma variável no programa. Vou usar a sintaxe Python para pseudocódigo imperativo; ele deve ser transparente na maior parte, com a indicação de que (a, b) = f(…)
os meios que a chamada para a função f
retorna um par e a
e b
são atribuídas do primeiro e segundo componente do par, respectivamente. Considere um loop
while test_condition():
do_stuff()
Vamos tornar o estado explícito.
state = initial_state
(state, cond) = test_condition(state)
while cond:
(state, cond) = test_condition(do_stuff(state))
Podemos traduzir isso em uma chamada recursiva. def loop(state):
define uma função chamada loop
.
def loop(state):
(state, cond) = test_condition(state)
if cond: return loop(do_stuff(state))
else: return state
state = loop(initial_state)
Isso usa apenas os seguintes conceitos, todos os quais podem ser expressados facilmente no cálculo lambda:
E assim podemos definir uma while
função para uma condição ( ) e um corpo ( ):
test_condition
do_stuff
Os loops variam dependendo da linguagem de programação, mas são sempre um caso especial de loops while, para que possam ser codificados da mesma maneira. Se o idioma de origem limitar a expressividade dos loops for, pode haver codificações mais simples. Por exemplo, “repetir vezes” é simplesmente composição da função vezes, onde a função é a transformação de estado que constitui o corpo do loop, e se é um numeral da Igreja, isso simplesmente se aplica à função do corpo do loop.
Uma abordagem alternativa ao estado é estender o cálculo lambda com primitivas de manipulação de estado. Se você fizer isso, a ordem da avaliação se tornará importante. Nesse caso, um loop while pode ser expresso diretamente com recursão.