2010-09-08 28 views
14

UserGuide của dự án scalacheck được đề cập đến máy phát điện có kích thước. Mã giải thíchMáy phát điện có kích thước trong scalacheck

def matrix[T](g:Gen[T]):Gen[Seq[Seq[T]]] = Gen.sized {size => 
val side = scala.Math.sqrt(size).asInstanceOf[Int] //little change to prevent compile-time exception 
Gen.vectorOf(side, Gen.vectorOf(side, g)) 
} 

không giải thích gì cho tôi. Sau một số thăm dò, tôi hiểu rằng độ dài của chuỗi được tạo ra không phụ thuộc vào kích thước thực của máy phát (có phương pháp thay đổi kích thước trong đối tượng Gen "Tạo phiên bản được thay đổi kích thước của máy phát" theo javadoc (có thể điều đó có nghĩa khác?)).

val g = Gen.choose(1,5) 
val g2 = Gen.resize(15, g) 
println(matrix(g).sample) // (1) 
println(matrix(g2).sample) // (2) 
//1,2 produce Seq with same length 

Bạn có thể giải thích cho tôi những gì tôi đã bỏ lỡ và cho tôi một số ví dụ về cách bạn sử dụng chúng trong mã thử nghiệm?

Trả lời

9

Phương thức vectorOf mà bạn sử dụng không được dùng nữa và bạn nên sử dụng phương thức listOf. Điều này tạo ra một danh sách các độ dài ngẫu nhiên, nơi chiều dài tối đa được giới hạn bởi kích thước của máy phát điện. Do đó bạn nên thay đổi kích thước máy phát điện mà thực sự tạo ra các danh sách thực tế nếu bạn muốn kiểm soát các yếu tố tối đa được tạo ra:


scala> val g1 = Gen.choose(1,5) 
g1: org.scalacheck.Gen[Int] = Gen() 

scala> val g2 = Gen.listOf(g1) 
g2: org.scalacheck.Gen[List[Int]] = Gen() 

scala> g2.sample 
res19: Option[List[Int]] = Some(List(4, 4, 4, 4, 2, 4, 2, 3, 5, 1, 1, 1, 4, 4, 1, 1, 4, 5, 5, 4, 3, 3, 4, 1, 3, 2, 2, 4, 3, 4, 3, 3, 4, 3, 2, 3, 1, 1, 3, 2, 5, 1, 5, 5, 1, 5, 5, 5, 5, 3, 2, 3, 1, 4, 3, 1, 4, 2, 1, 3, 4, 4, 1, 4, 1, 1, 4, 2, 1, 2, 4, 4, 2, 1, 5, 3, 5, 3, 4, 2, 1, 4, 3, 2, 1, 1, 1, 4, 3, 2, 2)) 

scala> val g3 = Gen.resize(10, g2) 
g3: java.lang.Object with org.scalacheck.Gen[List[Int]] = Gen() 

scala> g3.sample 
res0: Option[List[Int]] = Some(List(1)) 

scala> g3.sample 
res1: Option[List[Int]] = Some(List(4, 2)) 

scala> g3.sample 
res2: Option[List[Int]] = Some(List(2, 1, 2, 4, 5, 4, 2, 5, 3)) 
18

Các vectorOf (mà bây giờ được thay thế bằng listOf) tạo danh sách với một kích thước mà phụ thuộc (tuyến tính) trên tham số kích thước mà ScalaCheck đặt khi nó đánh giá một trình tạo. Khi ScalaCheck kiểm tra một thuộc tính, nó sẽ tăng tham số kích thước này cho mỗi phép thử, dẫn đến các thuộc tính được kiểm tra với các danh sách lớn hơn và lớn hơn (nếu sử dụng listOf).

Nếu bạn tạo trình tạo ma trận bằng cách chỉ sử dụng trình tạo kiểu listOf theo kiểu lồng nhau, bạn sẽ nhận được ma trận có kích thước phụ thuộc vào hình vuông của thông số kích thước. Do đó khi sử dụng một máy phát điện như vậy trong một thuộc tính, bạn có thể kết thúc với các ma trận rất lớn, vì ScalaCheck tăng tham số kích thước cho mỗi lần chạy thử nghiệm. Tuy nhiên, nếu bạn sử dụng bộ phối hợp máy phát điện resize theo cách được thực hiện trong Hướng dẫn sử dụng ScalaCheck, kích thước ma trận cuối cùng của bạn phụ thuộc tuyến tính vào tham số kích thước, dẫn đến hiệu suất đẹp hơn khi kiểm tra các thuộc tính của bạn.

Bạn thực sự không cần phải sử dụng máy tổ hợp máy phát điện resize thường xuyên. Nếu bạn cần tạo các danh sách bị giới hạn bởi một số kích thước cụ thể, tốt hơn bạn nên làm một cái gì đó giống như ví dụ dưới đây, vì không đảm bảo rằng máy phát điện listOf/containerOf thực sự sử dụng thông số kích thước theo cách bạn mong đợi.

def genBoundedList(maxSize: Int, g: Gen[T]): Gen[List[T]] = { 
    Gen.choose(0, maxSize) flatMap { sz => Gen.listOfN(sz, g) } 
} 
+0

Đây là ví dụ hay, cảm ơn. Rất minh họa. –

+1

Điều này dẫn tôi đến 'Gen.frequency ((10, 2), (5, 3), (1, 1)). FlatMap (Gen.listOfN (_, tên))' đó là chính xác những gì tôi cần! –

Các vấn đề liên quan