Determinazione delle funzioni utilizzando PRNG in Clojure e linguaggi funzionali

5

Sono un po 'sorpreso da una frase trovata nel libro "Programmazione Clojure" (1 ° [e solo come scrivo questa !?] edizione), pagina 78:

It should be obvious that it's impossible to deterministically test a function that depends upon a random number generator

Beh, per me non è affatto ovvio.

Per prima cosa nel contesto il libro parla sicuramente di un PRNG (quella frase segue solo una menzione di java.util.Random , che è un PRNG), non una vera fonte casuale.

Visto che i linguaggi funzionali che supportano la funzione di ordine superiore possono essere, beh, trasmessi funzioni ... Perché non passare semplicemente la funzione generatore casuale stessa alla funzione che vuoi essere in grado di testare in modo deterministico?

Se ho qualcosa di simile alla seguente funzione (è solo un esempio) e il PRNG stesso è deterministico, perché sarebbe impossibile testare in modo deterministico la seguente funzione:

(defn shuffle-deck [deck  last-generated-number   prngf]
      ...)

Mi rendo conto che invece di mantenere un riferimento (globale?) al tuo generatore casuale, devi mantenere un riferimento all'ultimo numero generato (e aggiornarlo di conseguenza) ma questo è fondamentalmente.

Puoi quindi testare / riprodurre il comportamento di qualsiasi funzione utilizzando un PRNG, purché tu passi il PRNG e "il numero casuale al quale sei attualmente".

Non è diverso dai motori di gioco deterministici (come Blizzard's Warcraft III) in cui i replay contengono solo gli input del giocatore, l'ora in cui sono avvenuti e il seme generale al PRNG.

Fondamentalmente sono un po 'confuso: ho sempre visto PRNG come qualcosa che non è "casualità" e ho l'impressione che i linguaggi funzionali che accettano la funzione di ordine superiore lo rendano particolarmente facile per riprodurre il comportamento delle funzioni in base al PRNG.

Quindi, quella frase del libro (che ho trovato un grande libro tra due) completa la spazzatura? Io certo non lo trovo "ovvio" affatto ...

    
posta Cedric Martin 05.01.2013 - 18:22
fonte

2 risposte

5

Dipende da ciò che l'autore aveva in mente quando ha fatto la dichiarazione. Sicuramente hai ragione che, usando un PRNG deterministico, puoi testare funzioni che sono deterministiche diverse dal PRNG che usano.

D'altra parte, se quello che stai testando dipende dal PRNG che ha un comportamento comune a loro (come avere almeno un certo periodo o una particolare distribuzione) e il tuo test PRNG non fornisce quei comportamenti, lo farai interrompi i test (o almeno li neutralizza).

In generale, tuttavia, considererei la frase non corretta. È normale usare i PRNG deterministici per testare in modo deterministico le funzioni che li utilizzano come input.

    
risposta data 05.01.2013 - 19:03
fonte
3

La citazione proviene da un paragrafo che va così:

It should be obvious that it’s impossible to deterministically test a function that depends upon a random number generator. For all intents and purposes however, the same is true of any function that depends upon or produces external state, since it is often very difficult to enumerate (...) all the potential edge cases and failure conditions related to that state. This is what mocks are for in testing, to dummy up an external data source or sink so that it will reliably behave in ways we know ahead of time so as to provoke particular results from a function under test. (...)

Il paragrafo proviene da una sezione sulle pure funzioni che si concentra su come le pure funzioni differiscono dalle funzioni non pure, cioè il determinismo che deriva dal fatto che l'output è una funzione dell'input e dell'input da solo - nessuna dipendenza da un esterno stato. RNG è utilizzato come esempio di tale stato esterno, ma lo sono anche il numero di follower di Twitter o il saldo del conto bancario.

Ciò che l'autore voleva dire è che non è possibile testare in modo deterministico una funzione come questa:

(defn addRandom [x]  
  (+ x (rand-int 10)))

dato che c'è uno stato esterno coinvolto e chiamando (addRandom 5) due volte potresti restituire due risultati diversi.

Ora, puoi refactoring questa funzione per rompere la dipendenza dalla chiamata rand. Ma allora non avrai un function that depends upon a RNG . Avresti una funzione di ordine superiore che accetta una funzione che fornisce un numero che potrebbe o non potrebbe essere casuale, oppure una funzione che richiede una coppia di numeri e così via. Avresti una funzione pura che potresti ragionare in modo affidabile, dato che hai escluso lo stato esterno dall'equazione. Ma sarebbe una funzione diversa da quella che hai iniziato - una che la frase che hai citato non si applica più.

    
risposta data 05.01.2013 - 20:51
fonte