mu
change
commit 7bc04b20e24f7b0fc2c3e003765695424d412849
author Alpha Chen <alpha@kejadlen.dev>
date
parent fb7c012f
diff --git a/lib/minitest/thesis.rb b/lib/minitest/thesis.rb
index ae42463..44c190e 100644
--- a/lib/minitest/thesis.rb
+++ b/lib/minitest/thesis.rb
@@ -193,9 +193,9 @@ module Minitest
     class Possibility
       attr_reader :produce, :name
 
-      def initialize(produce, name: "TODO")
-        @produce = produce
+      def initialize(name = "TODO", &produce)
         @name = name
+        @produce = produce
       end
 
       def inspect = name
@@ -203,41 +203,34 @@ module Minitest
 
       # "Returns a `Possibility` where values come from applying `f` to some possible value for `self`."
       def map(&f)
-        self.class.new(
-          ->(test_case) { f.(test_case.any(self)) },
-          name: "#{name}.map(TODO)",
-        )
+        self.class.new("#{name}.map(TODO)") {|tc| f.call(tc.any(self)) }
       end
 
       # Returns a `Possibility` where values come from applying `f` (which
       # should return a new `Possibility` to some possible value for `self`
       # then returning a possible value from that.
       def bind(&f)
-        produce = ->(test_case) { test_case.any(f.(test_case.any(self))) }
-        self.class.new(produce, name: "#{name}.bind(TODO)")
+        self.class.new("#{name}.bind(TODO)") {|tc| tc.any(f.(tc.any(self))) }
       end
 
       # Returns a `Possibility` whose values are any possible value of `self`
       # for which `f` returns True.
       def satisfying(&f)
-        produce = ->(test_case) {
-          3.times do
+        self.class.new("#{name}.select(TODO)") {|test_case|
+          3.times.first {
             candidate = test_case.any(self)
-            return candidate if f.(candidate)
-          end
-          test_case.reject
+            candidate if f.(candidate)
+          } || test_case.reject
         }
-
-        self.class.new(produce, name: "#{name}.select(TODO)")
       end
     end
 
     # Any integer in the range [m, n] is possible
-    def integers(m, n) = Possibility.new(->(tc) { m + tc.choice(n - m) }, name: "integers(#{m}, #{n})")
+    def integers(m, n) = Possibility.new("integers(#{m}, #{n})") {|tc| m + tc.choice(n - m) }
 
     # Any lists whose elements are possible values from `elements` are possible.
     def lists(elements, min_size: 0, max_size: Float::INFINITY)
-      produce = ->(test_case) {
+      Possibility.new("lists(#{elements.name})") {|test_case|
         result = []
         loop do
           if result.length < min_size
@@ -252,33 +245,29 @@ module Minitest
         end
         result
       }
-
-      Possibility.new(produce, name: "lists(#{elements.name})")
     end
 
     # Only `value` is possible.
-    def just(value) = Possibility.new(->(_) { value }, name: "just(#{value})")
+    def just(value) = Possibility.new("just(#{value})") { value }
 
     # No possible values. i.e. Any call to `any` will reject the test case.
-    def nothing = Possibility.new(->(tc) { tc.reject })
+    def nothing = Possibility.new {|tc| tc.reject }
 
     # Possible values can be any value possible for one of `possibilities`.
     def mix_of(*possibilities)
       return nothing if possibilities.empty?
 
-      Possibility.new(
-        ->(tc) { tc.any(possibilities[tc.choice(possibilities.length - 1)]) },
-        name: "mix_of(#{possibilities.map(&:name).join(", ")})",
-      )
+      Possibility.new("mix_of(#{possibilities.map(&:name).join(", ")})") {|tc|
+        tc.any(possibilities[tc.choice(possibilities.length - 1)])
+      }
     end
 
     # Any tuple t of of length len(possibilities) such that t[i] is possible
     # for possibilities[i] is possible.
     def tuples(*possibilities)
-      Possibility.new(
-        ->(tc) { possibilities.map {|p| tc.any(p) } },
-        name: "tuples(#{possibilities.map(&:name).join(", ")})",
-      )
+      Possibility.new( "tuples(#{possibilities.map(&:name).join(", ")})") {|tc|
+        possibilities.map {|p| tc.any(p) }
+      }
     end
 
     # We cap the maximum amount of entropy a test case can use.
diff --git a/test/minitest/thesis_test.rb b/test/minitest/thesis_test.rb
index 49a56d6..e6a453b 100644
--- a/test/minitest/thesis_test.rb
+++ b/test/minitest/thesis_test.rb
@@ -31,10 +31,10 @@ class Minitest::ThesisTest < Minitest::Thesis
   # 1001]``, and then lowering the length by two, turning it into ``[1001]`` as
   # desired.
   def test_finds_small_list_even_with_bad_lists
-    bad_list = Possibility.new(
-      ->(tc) { n = tc.choice(10); Array.new(n) { tc.choice(10_000) }},
-      name: "bad_list",
-    )
+    bad_list = Possibility.new("bad_list") {|tc|
+      n = tc.choice(10)
+      Array.new(n) { tc.choice(10_000) }
+    }
 
     (0...10).each do |seed|
       out, _ = capture_io do
@@ -321,7 +321,10 @@ class Minitest::ThesisTest < Minitest::Thesis
 
   def test_selected_possibility
     run_test("selected_possibility", database: {}) do |tc|
-      n = tc.any(integers(0, 5).satisfying(&:even?))
+      n = tc.any(
+        integers(0, 5)
+          .satisfying(&:even?)
+      )
       assert n.even?
     end
   end