escolha não-determinística com amb-operador
-
22-08-2019 - |
Solução
Sim, yield return
faz uma forma de continuação. Embora para muitos casos úteis, Linq fornece operadores funcionais que permitem que você conecte juntos um gerador de seqüência preguiçoso, por isso, de fato, em C # 3, não é necessário usar yield return
tanto (exceto ao adicionar mais extensões Linq de estilo de sua preferência para lacunas plugue na biblioteca, por exemplo, Zip, Unfold).
No exemplo que fatorar um número inteiro pela força bruta. Essencialmente o mesmo exemplo em C # pode ser feito com o built-in operadores LINQ:
var factors = Enumerable.Range(2, 100)
.Join(Enumerable.Range(2, 100),
n => 1, n => 1, (i, j) => new { i, j })
.First(v => v.i*v.j == 481);
Console.WriteLine("Factors are " + factors.i + ", " + factors.j);
Aqui, os pontos de partida são as minhas duas chamadas para Enumerable.Range
, que é embutido para Linq, mas você pode implementar-se como:
IEnumerable<int> Range(int start, int stop)
{
for (int n = start; n < stop; n++)
yield return n;
}
Existem dois parâmetros ímpar, o n => 1
, parâmetros n => 1
para Join
. Eu estou escolhendo 1 como o valor da chave para Join
para uso quando combinando-se itens, portanto, todas as combinações irá corresponder e assim que eu começar a testar todas as combinações de números das faixas.
Então eu ligar o par de valores em uma espécie de tupla (um tipo anônimo) com:
(i, j) => new { i, j })
Finalmente, eu pegar o primeiro tal tupla para a qual o meu teste está satisfeito:
.First(v => v.i*v.j == 481);
Atualizar
O código dentro da chamada para First
não precisa ser meramente uma expressão de teste curto. Pode ser um monte de código imperativo que precisa ser "reiniciado" se o teste falhar:
.First(v =>
{
Console.WriteLine("Aren't lambdas powerful things?");
return v.i*v.j == 481;
);
Assim, a parte do programa que potencialmente precisa ser reiniciado com valores diferentes vai nesse lambda. Sempre que lambda quer reiniciar-se com valores diferentes, ele só retorna false -. O equivalente de chamar amb
sem argumentos
Outras dicas
Esta não é uma resposta à sua pergunta, mas você pode obter o que deseja.
amb é usado para a computação não-determinístico. Como você deve saber, Prolog é uma linguagem não-determinístico usando a noção de unificação de valores se ligam a variáveis ??(basicamente o que amb acaba fazendo).
Não há uma implementação desta funcionalidade em C #, chamado YieldProlog. Como você adivinhou, o operador de rendimento é um requisito importante para isso.