Qqwy/ruby-prop_check

View on GitHub
lib/prop_check/helper.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
module PropCheck
  ##
  # Helper functions that have no other place to live
  module Helper
    extend self
    ##
    # Creates a (potentially lazy) Enumerator
    # starting with `elem`
    # with each consecutive element obtained
    # by calling `operation` on the previous element.
    #
    #   >> Helper.scanl(0, &:next).take(10).force
    #   => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    #   >> Helper.scanl([0, 1]) { |curr, next_elem| [next_elem, curr + next_elem] }.map(&:first).take(10).force
    #   => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
    def scanl(elem, &operation)
      Enumerator.new do |yielder|
        acc = elem
        loop do
          # p acc
          yielder << acc
          acc = operation.call(acc)
        end
      end.lazy
    end

    ##
    # allow lazy appending of two (potentially lazy) enumerators:
    #   >> PropCheck::Helper::LazyAppend.lazy_append([1,2,3],[4,5.6]).to_a
    #   => [1,2,3,4,5,6]
    def lazy_append(this_enumerator, other_enumerator)
      [this_enumerator, other_enumerator].lazy.flat_map(&:lazy)
    end

    def call_splatted(val, &block)
      # Handle edge case where Ruby >= 3 behaves differently than Ruby <= 2
      # c.f. https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/#other-minor-changes-empty-hash
      return block.call({}) if val.is_a?(Hash) && val.empty?
      return block.call(**val) if val.is_a?(Hash) && val.keys.all? { |k| k.is_a?(Symbol) }

      block.call(val)
    end
  end
end