(Tôi không biết Erlang và tôi không thể viết Haskell, nhưng tôi nghĩ tôi vẫn có thể trả lời)
Vâng, trong cuộc phỏng vấn đó, ví dụ về một thư viện tạo số ngẫu nhiên được đưa ra. Đây là một giao diện trạng thái có thể:
# 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)
Đầu ra có thể 5 2 7
. Đối với một người thích sự bất biến, điều này hoàn toàn sai! Nó nên như vậy 5 5 5
, bởi vì chúng ta đã gọi phương thức trên cùng một đối tượng.
Vì vậy, một giao diện phi trạng thái sẽ là gì? Chúng ta có thể xem chuỗi các số ngẫu nhiên như một danh sách được đánh giá một cách lười biếng, trong đó next
thực sự lấy ra đầu:
let rng = RNG(seed)
let n : rng = rng in
print n
let n : rng = rng in
print n
let n : rng in
print n
Với giao diện như vậy, chúng ta luôn có thể trở lại trạng thái trước đó. Nếu hai đoạn mã của bạn tham chiếu đến cùng một RNG, chúng thực sự sẽ có cùng một chuỗi số. Trong một tư duy chức năng, điều này là rất mong muốn.
Thực hiện điều này trong một ngôn ngữ nhà nước không phải là phức tạp. Ví dụ:
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))
Một khi bạn thêm một chút đường cú pháp để nó cảm thấy giống như một danh sách, điều này thực sự khá hay.