module Puppet::Pops::Types::Iterable
Public Class Methods
Produces an `Iterable` for one of the following types with the following characterstics:
`String` - yields each character in the string `Array` - yields each element in the array `Hash` - yields each key/value pair as a two element array `Integer` - when positive, yields each value from zero to the given number `PIntegerType` - yields each element from min to max (inclusive) provided min < max and neither is unbounded. `PEnumtype` - yields each possible value of the enum. `Range` - yields an iterator for all elements in the range provided that the range start and end
are both integers or both strings and start is less than end using natural ordering.
`Dir` - yields each name in the directory
An `ArgumentError` is raised for all other objects.
@param my_caller [Object] The calling object to reference in errors @param obj [Object] The object to produce an `Iterable` for @param infer_elements [Boolean] Whether or not to recursively infer all elements of obj. Optional
@return [Iterable,nil] The produced `Iterable` @raise [ArgumentError] In case an `Iterable` cannot be produced @api public
# File lib/puppet/pops/types/iterable.rb 34 def self.asserted_iterable(my_caller, obj, infer_elements = false) 35 iter = self.on(obj, nil, infer_elements) 36 raise ArgumentError, "#{my_caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? 37 iter 38 end
Produces an `Iterable` for one of the following types with the following characteristics:
`String` - yields each character in the string `Array` - yields each element in the array `Hash` - yields each key/value pair as a two element array `Integer` - when positive, yields each value from zero to the given number `PIntegerType` - yields each element from min to max (inclusive) provided min < max and neither is unbounded. `PEnumtype` - yields each possible value of the enum. `Range` - yields an iterator for all elements in the range provided that the range start and end
are both integers or both strings and start is less than end using natural ordering.
`Dir` - yields each name in the directory
The value `nil` is returned for all other objects.
@param o [Object] The object to produce an `Iterable` for @param element_type [PAnyType] the element type for the iterator. Optional @param infer_elements [Boolean] if element_type is nil, whether or not to recursively
infer types for the entire collection. Optional
@return [Iterable,nil] The produced `Iterable` or `nil` if it couldn't be produced
@api public
# File lib/puppet/pops/types/iterable.rb 62 def self.on(o, element_type = nil, infer_elements = true) 63 case o 64 when IteratorProducer 65 o.iterator 66 when Iterable 67 o 68 when String 69 Iterator.new(PStringType.new(PIntegerType.new(1, 1)), o.each_char) 70 when Array 71 if o.empty? 72 Iterator.new(PUnitType::DEFAULT, o.each) 73 else 74 if element_type.nil? && infer_elements 75 tc = TypeCalculator.singleton 76 element_type = PVariantType.maybe_create(o.map {|e| tc.infer_set(e) }) 77 end 78 Iterator.new(element_type, o.each) 79 end 80 when Hash 81 # Each element is a two element [key, value] tuple. 82 if o.empty? 83 HashIterator.new(PHashType::DEFAULT_KEY_PAIR_TUPLE, o.each) 84 else 85 if element_type.nil? && infer_elements 86 tc = TypeCalculator.singleton 87 element_type = PTupleType.new([ 88 PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }), 89 PVariantType.maybe_create(o.values.map {|e| tc.infer_set(e) })], PHashType::KEY_PAIR_TUPLE_SIZE) 90 end 91 HashIterator.new(element_type, o.each_pair) 92 end 93 when Integer 94 if o == 0 95 Iterator.new(PUnitType::DEFAULT, o.times) 96 elsif o > 0 97 IntegerRangeIterator.new(PIntegerType.new(0, o - 1)) 98 else 99 nil 100 end 101 when PIntegerType 102 # a finite range will always produce at least one element since it's inclusive 103 o.finite_range? ? IntegerRangeIterator.new(o) : nil 104 when PEnumType 105 Iterator.new(o, o.values.each) 106 when PTypeAliasType 107 on(o.resolved_type) 108 when Range 109 min = o.min 110 max = o.max 111 if min.is_a?(Integer) && max.is_a?(Integer) && max >= min 112 IntegerRangeIterator.new(PIntegerType.new(min, max)) 113 elsif min.is_a?(String) && max.is_a?(String) && max >= min 114 # A generalized element type where only the size is inferred is used here since inferring the full 115 # range might waste a lot of memory. 116 if min.length < max.length 117 shortest = min 118 longest = max 119 else 120 shortest = max 121 longest = min 122 end 123 Iterator.new(PStringType.new(PIntegerType.new(shortest.length, longest.length)), o.each) 124 else 125 # Unsupported range. It's either descending or nonsensical for other reasons (float, mixed types, etc.) 126 nil 127 end 128 else 129 # Not supported. We cannot determine the element type 130 nil 131 end 132 end
Answers the question if there is an end to the iteration. Puppet does not currently provide any unbounded iterables.
@return [Boolean] `true` if the iteration is unbounded
# File lib/puppet/pops/types/iterable.rb 138 def self.unbounded?(object) 139 case object 140 when Iterable 141 object.unbounded? 142 when String,Integer,Array,Hash,Enumerator,PIntegerType,PEnumType,Dir 143 false 144 else 145 TypeAsserter.assert_instance_of('', PIterableType::DEFAULT, object, false) 146 !object.respond_to?(:size) 147 end 148 end
Public Instance Methods
# File lib/puppet/pops/types/iterable.rb 150 def each(&block) 151 step(1, &block) 152 end
# File lib/puppet/pops/types/iterable.rb 154 def element_type 155 PAnyType::DEFAULT 156 end
# File lib/puppet/pops/types/iterable.rb 175 def hash_style? 176 false 177 end
# File lib/puppet/pops/types/iterable.rb 158 def reverse_each(&block) 159 # Default implementation cannot propagate reverse_each to a new enumerator so chained 160 # calls must put reverse_each last. 161 raise ArgumentError, 'reverse_each() is not implemented' 162 end
# File lib/puppet/pops/types/iterable.rb 164 def step(step, &block) 165 # Default implementation cannot propagate step to a new enumerator so chained 166 # calls must put stepping last. 167 raise ArgumentError, 'step() is not implemented' 168 end
# File lib/puppet/pops/types/iterable.rb 170 def to_a 171 raise Puppet::Error, 'Attempt to create an Array from an unbounded Iterable' if unbounded? 172 super 173 end
# File lib/puppet/pops/types/iterable.rb 179 def unbounded? 180 true 181 end