Primeiro, vamos examinar o que é verdadeiro e falso e o que lhes dá significado em primeiro lugar.
podemos construir uma estrutura chamada if a então b else c no cálculo lambda da seguinte maneira:
(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)
Em JavaScript, fica assim:
(function(ifThenElse) {
// use ifThenElse
})(function(a) {
return function(b) {
return function(c) {
return a(b)(c);
};
};
});
para que IfThenElse seja útil, precisamos de uma função "true" que escolha direita ou esquerda, e faça isso enquanto ignora a outra opção, ou de uma função "false" que escolha a opção "true".
Podemos definir essas funções da seguinte maneira:
(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)
em JavaScript, fica assim:
(function(True) {
// use True
})(function(a) {
return function(b) {
return a;
}
});
(function(False) {
// use True
})(function(a) {
return function(b) {
return b;
}
});
agora podemos fazer o seguinte
(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())
sendo doThis e doThat (\ a. ()) porque o cálculo lambda não oferece nenhum serviço, como printing / math / strings, tudo o que podemos fazer é não fazer nada e dizer que fizemos (e depois trapacear substituindo-o por serviços em nosso sistema que fornece efeitos colaterais que queremos)
então vamos ver isso em ação.
(function(True) {
return (function(False) {
return (function(ifThenElse) {
return (function(doThis) {
return (function(doThat) {
return ifThenElse(True)(doThis)(doThat);
});
});
});
})
})(function(a) {
return function(b) {
return a;
}
})(function(a) {
return function(b) {
return b;
}
})(function(a) {
return function(b) {
return function(c) {
return a(b)(c);
};
};
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();
Esse é um ambiente profundo que poderia ser simplificado se tivéssemos permissão para usar matrizes / mapas / argumentos / ou mais de uma instrução para dividir em várias funções, mas eu quero manter o mais puro possível, me limitando às funções de exatamente um argumento só.
observe que o nome Verdadeiro / Falso não tem significado inerente, podemos renomeá-los facilmente para sim / não, esquerda / direita, direita / esquerda, zero / um, maçã / laranja. Tem significado que, qualquer que seja a escolha feita, é causada apenas pelo tipo de escolha. Portanto, se "ESQUERDA" for impresso, sabemos que o seletor só pode ser verdadeiro e, com base nesse conhecimento, podemos orientar nossas decisões adicionais.
Então, para resumir
function ChooseRight(left) {
return function _ChooseRight_inner(right) {
return right;
}
}
function ChooseLeft(left) {
return function _ChooseLeft_inner(right) {
return left;
}
}
var env = {
'0': ChooseLeft,
'1': ChooseRight,
'false': ChooseRight,
'true': ChooseLeft,
'no': ChooseRight
'yes': ChooseLeft,
'snd': ChooseRight,
'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];
// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
console.log(self, self ? env['true'] : env['false']);
return self ? env['true'] : env['false'];
}
lambda_decodeBoolean('one' === 'two')(function() {
console.log('one is two');
})(function() {
console.log('one is not two');
})();
lambda_decodeBoolean('one' === 'one')(function() {
console.log('one is one');
})(function() {
console.log('one is not one');
})();