2014-12-19 21 views
5

Sotto funzione getRandomString genera una stringa casuale da un elenco di caratteri:si tratta di una pura funzione a Scala

def genRandomInt(lb: Int, ub: Int) = { 
    val rnd = new scala.util.Random 
    lb + rnd.nextInt(ub) 
    }  
    def getRandomString(validChars: List[Char]) = { 

    val size = validChars.size 

    val random = new scala.util.Random 
    val stringBuilder = new StringBuilder 
    val rnd = genRandomInt(0, size) 
    val sb = new StringBuilder 

    for (i <- 0 to size - 1) { 
     val rnd = genRandomInt(0, size) 
     sb.append(validChars(rnd)) 
    } 

    sb.toString 
    }            //> getRandomString: (validChars: List[Char])String 

    val rs = getRandomString(('a' to 'j').toList) 
                //> rs : String = aghdjjhjge 

È getRandomString un esempio di una funzione di puro in quanto non modifica lo stato?

+3

"se il suo argomento non cambia tra più chiamate, quindi il suo risultato non cambierà. " - Puoi mostrarci un esempio? Sono abbastanza sicuro che non è vero, ma non posso testarlo perché il tuo codice non viene compilato. –

+0

@ Jörg W Mittag alla tua destra il risultato cambierà, è stata rimossa questa frase. Questo codice non è referenziale trasparente. Questo codice viene compilato per me nel foglio di lavoro con Eclipse Kepler Scala versione 2.11 –

+0

'error: not found: value genRandomInt'. Questo sembra essere un metodo di un binding di Scala MATLAB? Ma non ho MATLAB. –

risposta

8

No, perché in effetti modifica lo stato. new scala.util.Random alla fine richiama new java.util.Random, che accede e modifica un valore statico (ad esempio globale), mutabile AtomicLong chiamato seedUniquifier. E quindi se questo metodo viene chiamato più volte, il risultato cambierà.

Questo è un buon esempio di come i metodi apparentemente innocenti possono nascondere gli accessi allo stato globale mutabile, cosa che sarebbe vietata in un linguaggio funzionale più rigido come Haskell (sebbene tale approccio abbia i suoi problemi).

1

No perché new scala.util.Random().nextInt ... restituisce qualcosa di diverso ogni volta, che è spiegato in modo convincente da Imm.

Tuttavia, è sufficiente passare un seme, quindi sarà una funzione pura perché restituirà sempre la stessa stringa casuale. È possibile aggiungere il seme come parametro o semplicemente correggerlo all'interno del metodo stringa casuale.

Infine, ho notato che hai scritto una quantità enorme di codice per generare una stringa casuale. Ti suggerisco di dare un'occhiata a ScalaCheck che ha pile di utili funzioni per la generazione di cose casuali (per i test di unità), String viene fornito immediatamente.

Se non si vuole tirare in una libreria, si può ancora fare quel codice molto più conciso:

def randomString(fromChars: List[Char], length: Int): String = { 
    val rand = new Random(1234) // Now it's pure functional because the seed is fixed 
    val fromCharsSize = fromChars.size // to save us repeatedly counting 
    List.fill(length)(fromChars(rand.nextInt(fromCharsSize))).mkString 
} 

osservarlo ritorna stesso valore ogni volta

scala> randomString("asdf".toList, 10) 
res0: String = dsfafssdsa 

scala> randomString("asdf".toList, 10) 
res1: String = dsfafssdsa 
Problemi correlati