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 33 def self.asserted_iterable(my_caller, obj, infer_elements = false) 34 iter = self.on(obj, nil, infer_elements) 35 raise ArgumentError, "#{my_caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? 36 iter 37 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 61 def self.on(o, element_type = nil, infer_elements = true) 62 case o 63 when IteratorProducer 64 o.iterator 65 when Iterable 66 o 67 when String 68 Iterator.new(PStringType.new(PIntegerType.new(1, 1)), o.each_char) 69 when Array 70 if o.empty? 71 Iterator.new(PUnitType::DEFAULT, o.each) 72 else 73 if element_type.nil? && infer_elements 74 tc = TypeCalculator.singleton 75 element_type = PVariantType.maybe_create(o.map {|e| tc.infer_set(e) }) 76 end 77 Iterator.new(element_type, o.each) 78 end 79 when Hash 80 # Each element is a two element [key, value] tuple. 81 if o.empty? 82 HashIterator.new(PHashType::DEFAULT_KEY_PAIR_TUPLE, o.each) 83 else 84 if element_type.nil? && infer_elements 85 tc = TypeCalculator.singleton 86 element_type = PTupleType.new([ 87 PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }), 88 PVariantType.maybe_create(o.values.map {|e| tc.infer_set(e) })], PHashType::KEY_PAIR_TUPLE_SIZE) 89 end 90 HashIterator.new(element_type, o.each_pair) 91 end 92 when Integer 93 if o == 0 94 Iterator.new(PUnitType::DEFAULT, o.times) 95 elsif o > 0 96 IntegerRangeIterator.new(PIntegerType.new(0, o - 1)) 97 else 98 nil 99 end 100 when PIntegerType 101 # a finite range will always produce at least one element since it's inclusive 102 o.finite_range? ? IntegerRangeIterator.new(o) : nil 103 when PEnumType 104 Iterator.new(o, o.values.each) 105 when PTypeAliasType 106 on(o.resolved_type) 107 when Range 108 min = o.min 109 max = o.max 110 if min.is_a?(Integer) && max.is_a?(Integer) && max >= min 111 IntegerRangeIterator.new(PIntegerType.new(min, max)) 112 elsif min.is_a?(String) && max.is_a?(String) && max >= min 113 # A generalized element type where only the size is inferred is used here since inferring the full 114 # range might waste a lot of memory. 115 if min.length < max.length 116 shortest = min 117 longest = max 118 else 119 shortest = max 120 longest = min 121 end 122 Iterator.new(PStringType.new(PIntegerType.new(shortest.length, longest.length)), o.each) 123 else 124 # Unsupported range. It's either descending or nonsensical for other reasons (float, mixed types, etc.) 125 nil 126 end 127 else 128 # Not supported. We cannot determine the element type 129 nil 130 end 131 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 137 def self.unbounded?(object) 138 case object 139 when Iterable 140 object.unbounded? 141 when String,Integer,Array,Hash,Enumerator,PIntegerType,PEnumType,Dir 142 false 143 else 144 TypeAsserter.assert_instance_of('', PIterableType::DEFAULT, object, false) 145 !object.respond_to?(:size) 146 end 147 end
Public Instance Methods
# File lib/puppet/pops/types/iterable.rb 149 def each(&block) 150 step(1, &block) 151 end
# File lib/puppet/pops/types/iterable.rb 153 def element_type 154 PAnyType::DEFAULT 155 end
# File lib/puppet/pops/types/iterable.rb 174 def hash_style? 175 false 176 end
# File lib/puppet/pops/types/iterable.rb 157 def reverse_each(&block) 158 # Default implementation cannot propagate reverse_each to a new enumerator so chained 159 # calls must put reverse_each last. 160 raise ArgumentError, 'reverse_each() is not implemented' 161 end
# File lib/puppet/pops/types/iterable.rb 163 def step(step, &block) 164 # Default implementation cannot propagate step to a new enumerator so chained 165 # calls must put stepping last. 166 raise ArgumentError, 'step() is not implemented' 167 end
# File lib/puppet/pops/types/iterable.rb 169 def to_a 170 raise Puppet::Error, 'Attempt to create an Array from an unbounded Iterable' if unbounded? 171 super 172 end
# File lib/puppet/pops/types/iterable.rb 178 def unbounded? 179 true 180 end