scelta non deterministica con AMB-operator
-
22-08-2019 - |
Soluzione
Sì, yield return
fa una forma di continuità. Anche se per molti casi utili, LINQ offre agli operatori funzionali che consentono di collegare insieme un generatore di sequenza pigro, quindi in realtà in C # 3 non è necessario utilizzare yield return
tanto (tranne quando l'aggiunta di ulteriori estensioni in stile Linq del proprio per colmare le lacune nella biblioteca, quale ZIP, Unfold).
Nell'esempio abbiamo fattorizzare un intero con la forza bruta. In sostanza lo stesso esempio in C # può essere fatto con il built-in operatori 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);
Ecco i punti di partenza sono i miei due chiamate a Enumerable.Range
, che è built-in per Linq, ma si potrebbe implementare te stesso come:
IEnumerable<int> Range(int start, int stop)
{
for (int n = start; n < stop; n++)
yield return n;
}
Ci sono due parametri dispari, il n => 1
, parametri n => 1
a Join
. Rilevo 1 come il valore della chiave per Join
da utilizzare quando corrispondenza gli oggetti, quindi tutte le combinazioni corrisponderanno e così ho arrivare a testare ogni combinazione di numeri da gamme.
Poi mi giro la coppia di valori in una sorta di tupla (un tipo anonimo) con:
(i, j) => new { i, j })
Infine, prendo il primo tale tupla per il quale il mio test è soddisfatto:
.First(v => v.i*v.j == 481);
Aggiorna
Il codice all'interno della chiamata a First
non deve essere solo una breve espressione di prova. Può essere un bel po 'di codice imperativo che deve essere "riavviato" se il test fallisce:
.First(v =>
{
Console.WriteLine("Aren't lambdas powerful things?");
return v.i*v.j == 481;
);
Quindi la parte del programma che ha bisogno potenzialmente essere riavviato con valori diversi va in quel lambda. Ogni volta che lambda vuole riavviare stesso con valori diversi, restituisce semplicemente false -. L'equivalente di chiamare amb
senza argomenti
Altri suggerimenti
Questa non è una risposta alla tua domanda, ma si può ottenere quello che vuoi.
AMB viene utilizzato per il calcolo non deterministico. Come forse sapete, Prolog è un linguaggio non deterministico utilizzando il concetto di unificazione per associare i valori alle variabili (fondamentalmente ciò che amb finisce per fare).
C'è un'implementazione di questa funzionalità in C #, chiamato YieldProlog. Come avete indovinato, l'operatore resa è un requisito importante per questo.