{"action":"created","comment":{"url":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/50545812","id":50545812,"diff_hunk":"@@ -1,33 +1,72 @@\n # The Enumeration class provides default Enumerable::Enumerator creation for Puppet Programming Language\n # runtime objects that supports the concept of enumeration.\n #\n-class Puppet::Pops::Types::Enumeration\n-  # Produces an Enumerable::Enumerator for Array, Hash, Integer, Integer Range, and String.\n+module Puppet::Pops::Types\n+class Enumeration\n+\n+  # Produces an `Enumerator` for `String`, `Integer`, `PIntegerType` or anything that respond to `each` by\n+  # returning an `Enumerator`. The argument is returned in case it already is an `Enumerator`.\n+  #\n+  # @param caller [Function] The function that needs to coerce its argument to an enumeration\n+  # @param o [Object] The object to produce an `Enumerator` for\n+  # @return [Enumerator] The produced `Enumerator` or nil if it couldn't be produced\n+  # @raise [ArgumentError] In case an `Enumerator` cannot be produced\n+  # @api public\n+  def self.asserted_enumerable(caller, o)\n+    enum = self.enumerator(o)\n+    raise ArgumentError, \"#{caller.class.name}(): wrong argument type (#{o.class.name}; must be something enumerable.\" if enum.nil?\n+    enum\n+  end\n+\n+  # Produces an `Enumerator` for `String`, `Integer`, `PIntegerType` or anything that respond to `each` by\n+  # returning an `Enumerator`. The argument is returned in case it already is an `Enumerator`.\n   #\n+  # @param o [Object] The object to produce an `Enumerator` for\n+  # @return [Enumerator,nil] The produced `Enumerator` or `nil` if it couldn't be produced\n+  # @api public\n   def self.enumerator(o)\n     @@singleton ||= new\n     @@singleton.enumerator(o)\n   end\n \n-  # Produces an Enumerator for Array, Hash, Integer, Integer Range, and String.\n+  # Produces an `Enumerator` for `String`, `Integer`, `Range`, `PIntegerType` or anything that respond to `each` by\n+  # returning an `Enumerator`. The argument is returned in case it already is an `Enumerator` or an `Iterable`.\n   #\n+  # @param o [Object] The object to produce an `Enumerator` for\n+  # @return [Enumerator,nil] The produced `Enumerator` or `nil` if it couldn't be produced\n+  # @api public\n   def enumerator(o)\n     case o\n     when String\n-      x = o.chars\n-      # Ruby 1.9.3 returns an Enumerator, and 2.0.0 an Array\n-      x.is_a?(Array) ? x.each : x\n-    when Integer\n-      o.times\n+      EnumerationIterable.new(PStringType::DEFAULT, o.each_char)\n     when Array\n-      o.each\n-    when Hash\n-      o.each\n-    when Puppet::Pops::Types::PIntegerType\n-      # Not enumerable if representing an infinite range\n-      o.enumerable? ? o.each : nil\n+      EnumerationIterable.new(TypeCalculator.singleton.infer_and_reduce_type(o), o.each)\n+    when Integer\n+      o > 0 ? IntegerRangeIterator.new(PIntegerType.new(0, o - 1)) : nil\n+    when PIntegerType\n+      o.enumerable? ? IntegerRangeIterator.new(o) : nil\n+    when PEnumType\n+      EnumerationIterable.new(PStringType::DEFAULT, o.values)\n+    when Range\n+      min = o.min\n+      if min.is_a?(Integer)\n+        max = o.max\n+        max > min ? IntegerRangeIterator.new(PIntegerType.new(min, max)) : nil\n+      else\n+        # A generalized form of the inferred type for the 'min' is used here since inferring the full\n+        # range might waste a lot of memory.\n+        EnumerationIterable.new(TypeCalculator.singleton.infer(min).generalize, o.each)\n+      end\n+    when Enumerator, Iterable\n+      o\n     else\n-      nil\n+      begin\n+        result = o.each\n+        result.is_a?(Enumerator) ? result : nil","path":"lib/puppet/pops/types/enumeration.rb","position":80,"original_position":80,"commit_id":"ec8d3a0084ebfafa5c43eb510ca80e005d0690b6","original_commit_id":"ec8d3a0084ebfafa5c43eb510ca80e005d0690b6","user":{"login":"hlindberg","id":563066,"avatar_url":"https://avatars.githubusercontent.com/u/563066?v=3","gravatar_id":"","url":"https://api.github.com/users/hlindberg","html_url":"https://github.com/hlindberg","followers_url":"https://api.github.com/users/hlindberg/followers","following_url":"https://api.github.com/users/hlindberg/following{/other_user}","gists_url":"https://api.github.com/users/hlindberg/gists{/gist_id}","starred_url":"https://api.github.com/users/hlindberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hlindberg/subscriptions","organizations_url":"https://api.github.com/users/hlindberg/orgs","repos_url":"https://api.github.com/users/hlindberg/repos","events_url":"https://api.github.com/users/hlindberg/events{/privacy}","received_events_url":"https://api.github.com/users/hlindberg/received_events","type":"User","site_admin":false},"body":"Hm, we have no type information here, requires you to accept `Iterable[Any]`. Do we really need this very open ended solution? Can we require a richer API? As an example, if we allow producer functions, and we have return types, we do know the produced type. Perhaps have either another method enumerator(o, T) that you need to use if what you created does not have type information. (That implies that the values that will be emitted needs to be type checked before yielded).","created_at":"2016-01-22T15:01:39Z","updated_at":"2016-01-22T15:01:39Z","html_url":"https://github.com/puppetlabs/puppet/pull/4578#discussion_r50545812","pull_request_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578","_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/50545812"},"html":{"href":"https://github.com/puppetlabs/puppet/pull/4578#discussion_r50545812"},"pull_request":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578"}}},"pull_request":{"url":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578","id":56474427,"html_url":"https://github.com/puppetlabs/puppet/pull/4578","diff_url":"https://github.com/puppetlabs/puppet/pull/4578.diff","patch_url":"https://github.com/puppetlabs/puppet/pull/4578.patch","issue_url":"https://api.github.com/repos/puppetlabs/puppet/issues/4578","number":4578,"state":"open","locked":false,"title":"(PUP-5648) Add iterable type and runtime object","user":{"login":"thallgren","id":209495,"avatar_url":"https://avatars.githubusercontent.com/u/209495?v=3","gravatar_id":"","url":"https://api.github.com/users/thallgren","html_url":"https://github.com/thallgren","followers_url":"https://api.github.com/users/thallgren/followers","following_url":"https://api.github.com/users/thallgren/following{/other_user}","gists_url":"https://api.github.com/users/thallgren/gists{/gist_id}","starred_url":"https://api.github.com/users/thallgren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thallgren/subscriptions","organizations_url":"https://api.github.com/users/thallgren/orgs","repos_url":"https://api.github.com/users/thallgren/repos","events_url":"https://api.github.com/users/thallgren/events{/privacy}","received_events_url":"https://api.github.com/users/thallgren/received_events","type":"User","site_admin":false},"body":"This commit adds a new `Iterable` type to the Puppet type system\r\ntogether with a Ruby implementation of a runtime module with the\r\nsame name and three api private support classes. One that wraps\r\nan Enumerator, one that wraps an integer range, and one that takes\r\ncare of the stepping aspect of the Enumerator wrapper.\r\n\r\nThe commit also changes the iterative functions `each`, `filter`,\r\n`map`, `reduce`, and `slice` so that the type of their declared\r\n_enumerable_ parameter is `Iterable` instead of `Any`","created_at":"2016-01-19T14:41:55Z","updated_at":"2016-01-22T15:01:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b06b0e08a3dcdbe67b41f8710fee8f4653d30f24","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/issues/4578/comments","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/ec8d3a0084ebfafa5c43eb510ca80e005d0690b6","head":{"label":"thallgren:issue/pup-5648/iterable-type","ref":"issue/pup-5648/iterable-type","sha":"ec8d3a0084ebfafa5c43eb510ca80e005d0690b6","user":{"login":"thallgren","id":209495,"avatar_url":"https://avatars.githubusercontent.com/u/209495?v=3","gravatar_id":"","url":"https://api.github.com/users/thallgren","html_url":"https://github.com/thallgren","followers_url":"https://api.github.com/users/thallgren/followers","following_url":"https://api.github.com/users/thallgren/following{/other_user}","gists_url":"https://api.github.com/users/thallgren/gists{/gist_id}","starred_url":"https://api.github.com/users/thallgren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thallgren/subscriptions","organizations_url":"https://api.github.com/users/thallgren/orgs","repos_url":"https://api.github.com/users/thallgren/repos","events_url":"https://api.github.com/users/thallgren/events{/privacy}","received_events_url":"https://api.github.com/users/thallgren/received_events","type":"User","site_admin":false},"repo":{"id":15137589,"name":"puppet","full_name":"thallgren/puppet","owner":{"login":"thallgren","id":209495,"avatar_url":"https://avatars.githubusercontent.com/u/209495?v=3","gravatar_id":"","url":"https://api.github.com/users/thallgren","html_url":"https://github.com/thallgren","followers_url":"https://api.github.com/users/thallgren/followers","following_url":"https://api.github.com/users/thallgren/following{/other_user}","gists_url":"https://api.github.com/users/thallgren/gists{/gist_id}","starred_url":"https://api.github.com/users/thallgren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thallgren/subscriptions","organizations_url":"https://api.github.com/users/thallgren/orgs","repos_url":"https://api.github.com/users/thallgren/repos","events_url":"https://api.github.com/users/thallgren/events{/privacy}","received_events_url":"https://api.github.com/users/thallgren/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/thallgren/puppet","description":"Server automation framework and application","fork":true,"url":"https://api.github.com/repos/thallgren/puppet","forks_url":"https://api.github.com/repos/thallgren/puppet/forks","keys_url":"https://api.github.com/repos/thallgren/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thallgren/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thallgren/puppet/teams","hooks_url":"https://api.github.com/repos/thallgren/puppet/hooks","issue_events_url":"https://api.github.com/repos/thallgren/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/thallgren/puppet/events","assignees_url":"https://api.github.com/repos/thallgren/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/thallgren/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/thallgren/puppet/tags","blobs_url":"https://api.github.com/repos/thallgren/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thallgren/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thallgren/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/thallgren/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thallgren/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/thallgren/puppet/languages","stargazers_url":"https://api.github.com/repos/thallgren/puppet/stargazers","contributors_url":"https://api.github.com/repos/thallgren/puppet/contributors","subscribers_url":"https://api.github.com/repos/thallgren/puppet/subscribers","subscription_url":"https://api.github.com/repos/thallgren/puppet/subscription","commits_url":"https://api.github.com/repos/thallgren/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/thallgren/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/thallgren/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/thallgren/puppet/issues/comments{/number}","contents_url":"https://api.github.com/repos/thallgren/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/thallgren/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thallgren/puppet/merges","archive_url":"https://api.github.com/repos/thallgren/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thallgren/puppet/downloads","issues_url":"https://api.github.com/repos/thallgren/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/thallgren/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/thallgren/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/thallgren/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thallgren/puppet/labels{/name}","releases_url":"https://api.github.com/repos/thallgren/puppet/releases{/id}","deployments_url":"https://api.github.com/repos/thallgren/puppet/deployments","created_at":"2013-12-12T14:09:32Z","updated_at":"2015-01-21T18:51:48Z","pushed_at":"2016-01-22T12:01:56Z","git_url":"git://github.com/thallgren/puppet.git","ssh_url":"git@github.com:thallgren/puppet.git","clone_url":"https://github.com/thallgren/puppet.git","svn_url":"https://github.com/thallgren/puppet","homepage":"http://www.puppetlabs.com/puppet/introduction/","size":49453,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"puppetlabs:master","ref":"master","sha":"2e7e5c194de11450c2ea5bb6a0c924a05eb53dee","user":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":910744,"name":"puppet","full_name":"puppetlabs/puppet","owner":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/puppet","description":"Server automation framework and application","fork":false,"url":"https://api.github.com/repos/puppetlabs/puppet","forks_url":"https://api.github.com/repos/puppetlabs/puppet/forks","keys_url":"https://api.github.com/repos/puppetlabs/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/puppet/teams","hooks_url":"https://api.github.com/repos/puppetlabs/puppet/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/puppet/events","assignees_url":"https://api.github.com/repos/puppetlabs/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/puppet/tags","blobs_url":"https://api.github.com/repos/puppetlabs/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/puppet/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/puppet/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/puppet/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/puppet/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/puppet/subscription","commits_url":"https://api.github.com/repos/puppetlabs/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/puppet/issues/comments{/number}","contents_url":"https://api.github.com/repos/puppetlabs/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/puppet/merges","archive_url":"https://api.github.com/repos/puppetlabs/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/puppet/downloads","issues_url":"https://api.github.com/repos/puppetlabs/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/puppet/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/puppet/releases{/id}","deployments_url":"https://api.github.com/repos/puppetlabs/puppet/deployments","created_at":"2010-09-14T19:26:44Z","updated_at":"2016-01-22T02:08:33Z","pushed_at":"2016-01-22T12:01:57Z","git_url":"git://github.com/puppetlabs/puppet.git","ssh_url":"git@github.com:puppetlabs/puppet.git","clone_url":"https://github.com/puppetlabs/puppet.git","svn_url":"https://github.com/puppetlabs/puppet","homepage":"https://puppetlabs.com/puppet/what-is-puppet","size":78009,"stargazers_count":3764,"watchers_count":3764,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1558,"mirror_url":null,"open_issues_count":35,"forks":1558,"open_issues":35,"watchers":3764,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578"},"html":{"href":"https://github.com/puppetlabs/puppet/pull/4578"},"issue":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/4578"},"comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/4578/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/4578/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/puppet/statuses/ec8d3a0084ebfafa5c43eb510ca80e005d0690b6"}}}}