lib/xi/pattern/transforms.rb in xi-lang-0.1.2 vs lib/xi/pattern/transforms.rb in xi-lang-0.1.3

- old
+ new

@@ -208,22 +208,37 @@ break if is_empty end end end - # Traverses the pattern in order and then in reverse order + # Traverses the pattern in order and then in reverse order, skipping + # first and last values if +skip_extremes+ is true. # # @example - # peek (0..3).p.bounce #=> [0, 1, 2, 3, 3, 2, 1, 0] + # peek (0..3).p.bounce #=> [0, 1, 2, 3, 2, 1] + # peek 10.p.bounce #=> [10] # + # @example with skip_extremes=false + # peek (0..3).p.bounce(false) #=> [0, 1, 2, 3, 3, 2, 1, 0] + # + # @param skip_extremes [Boolean] Skip first and last values + # to avoid repeated values (default: true) # @return [Pattern] # - def bounce - Pattern.new(self, size: size * 2 - 1) do |y| - each.with_index { |v, i| y << v if i > 0 } - reverse_each.with_index { |v, i| y << v if i > 0 } - end + def bounce(skip_extremes=true) + return self if size == 0 || size == 1 + + Pattern.new(self, size: size * 2 - 1) { |y| + last_id = 0 + each.with_index { |v, i| + y << v + last_id = i + } + reverse_each.with_index { |v, i| + y << v unless skip_extremes && (i == 0 || i == last_id) + } + } end # Normalizes a pattern of values that range from +min+ to +max+ to 0..1 # # Values from pattern that do not respond to #- are ignored. @@ -304,11 +319,16 @@ # Based on +probability+, it yields original value or nil # TODO Document # def sometimes(probability=0.5) prob_pat = probability.p - Pattern.new(self, size: size * prob_pat.size) do |y| + + if times_pat.infinite? + fail ArgumentError, 'times must be a finite pattern' + end + + Pattern.new(self, size: size * prob_pat.reduce(:+)) do |y| prob_pat.each do |prob| each { |v| y << (rand < prob ? v : nil) } end end end @@ -316,10 +336,15 @@ # Repeats each value +times+ # TODO Document # def repeat_each(times) times_pat = times.p - Pattern.new(self, size: size * times_pat.size) do |y| + + if times_pat.infinite? + fail ArgumentError, 'times must be a finite pattern' + end + + Pattern.new(self, size: size * times_pat.reduce(:+)) do |y| times_pat.each do |t| each { |v| t.times { y << v } } end end end