(Я не знаю Ерланга, і я не можу написати Haskell, але я думаю, що все-таки можу відповісти)
Ну, в цьому інтерв'ю наведено приклад бібліотеки генерації випадкових чисел Ось можливий інтерпретаційний стан:
# create a new RNG
var rng = RNG(seed)
# every time we call the next(ceil) method, we get a new random number
print rng.next(10)
print rng.next(10)
print rng.next(10)
Вихід може бути 5 2 7
. Для того, хто любить незмінність, це явно неправильно! Це повинно бути 5 5 5
, тому що ми назвали метод на одному об’єкті.
То який би був інтерфейс без громадянства? Ми можемо розглядати послідовність випадкових чисел як ліниво оцінений список, де next
фактично виводиться голова:
let rng = RNG(seed)
let n : rng = rng in
print n
let n : rng = rng in
print n
let n : rng in
print n
З таким інтерфейсом ми завжди можемо повернутися до попереднього стану. Якщо дві частини вашого коду стосуються одного і того ж RNG, вони фактично отримають однакову послідовність чисел. Для функціонального мислення це дуже бажано.
Реалізовувати це на державній мові не так вже й складно. Наприклад:
import scala.util.Random
import scala.collection.immutable.LinearSeq
class StatelessRNG (private val statefulRNG: Random, bound: Int) extends LinearSeq[Int] {
private lazy val next = (statefulRNG.nextInt(bound), new StatelessRNG(statefulRNG, bound))
// the rest is just there to satisfy the LinearSeq trait
override def head = next._1
override def tail = next._2
override def isEmpty = false
override def apply(i: Int): Int = throw new UnsupportedOperationException()
override def length = throw new UnsupportedOperationException()
}
// print out three nums
val rng = new StatelessRNG(new Random(), 10)
rng.take(3) foreach (n => println(n))
Як тільки ви додасте трохи синтаксичного цукру, щоб він відчував себе у списку, це насправді дуже приємно.