{"action":"created","comment":{"url":"https://api.github.com/repos/lenskit/lenskit/pulls/comments/31171224","id":31171224,"diff_hunk":"@@ -0,0 +1,56 @@\n+/*\n+ * LensKit, an open source recommender systems toolkit.\n+ * Copyright 2010-2014 LensKit Contributors.  See CONTRIBUTORS.md.\n+ * Work on LensKit has been funded by the National Science Foundation under\n+ * grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU Lesser General Public License as\n+ * published by the Free Software Foundation; either version 2.1 of the\n+ * License, or (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\n+ * details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program; if not, write to the Free Software Foundation, Inc., 51\n+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n+ */\n+package org.lenskit.api;\n+\n+import java.util.List;\n+\n+/**\n+ * A set of results from a recommender operation.  Recommendation results conceptually map item\n+ * (or user, for a few operations) IDs to corresponding scores, and have some order over their IDs.\n+ * Depending on the operation that produced the result set, that order may be arbitrary, but\n+ * operations that find things (recommendation, related item and user queries) will usually\n+ * return results in order from most to least relevant or wanted.\n+ *\n+ * @param <E> The entry type (parameterized to make extension cleaner).\n+ */\n+public interface ResultList<E extends Result> extends List<E> {\n+    /**\n+     * Return a list of the item (or user) IDs in this result list.\n+     *\n+     * @return The list of IDs.\n+     */\n+    List<Long> idList();\n+\n+    /**\n+     * Convert this result list to a list with a different type of result.  Technically, this provides a runtime-checked\n+     * means of making the result list type *covariant* in its result type, since Java does not allow us to encode this\n+     * allowance in the type system.\n+     *\n+     * @param type The result type to cast to.  It is always valid for this type to be a supertype of `E`; the method\n+     *             will also succeed if every non-null result is an instance of this type (or one of its subtypes).\n+     * @param <T> The result type.\n+     * @return A result list statically typed to contain results of type `T`.\n+     * @throws IllegalArgumentException if not all results can be cast type type `T`.\n+     * @throws UnsupportedOperationException if the result list is mutable (very rare, only used for intermediate\n+     * working objects).\n+     */\n+    <T extends Result> ResultList<T> castResults(Class<T> type);","path":"lenskit-api/src/main/java/org/lenskit/api/ResultList.java","position":55,"original_position":55,"commit_id":"29235871ee6c8bcf883333eab60edd9818585021","original_commit_id":"29235871ee6c8bcf883333eab60edd9818585021","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"body":"`T extends Result` is what we want, so that we can up-cast.\r\n\r\nThe canonical use of this will be to implement the non-detailed `recommend` method:\r\n\r\n```java\r\npublic ResultList<T> recommend(long user, ...) {\r\n    return recommendWithDetails(user, ...).castResults(Result.class);\r\n}\r\n```\r\n\r\nHowever, if we mandate that result lists *always* be immutable, then it is safe to just do an unchecked cast.","created_at":"2015-05-27T19:31:43Z","updated_at":"2015-05-27T19:31:43Z","html_url":"https://github.com/lenskit/lenskit/pull/733#discussion_r31171224","pull_request_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733","_links":{"self":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/comments/31171224"},"html":{"href":"https://github.com/lenskit/lenskit/pull/733#discussion_r31171224"},"pull_request":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733"}}},"pull_request":{"url":"https://api.github.com/repos/lenskit/lenskit/pulls/733","id":35973332,"html_url":"https://github.com/lenskit/lenskit/pull/733","diff_url":"https://github.com/lenskit/lenskit/pull/733.diff","patch_url":"https://github.com/lenskit/lenskit/pull/733.patch","issue_url":"https://api.github.com/repos/lenskit/lenskit/issues/733","number":733,"state":"open","locked":false,"title":"Create result set APIs (pre-review)","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"body":"This works on #727.\r\n\r\nWe are not ready to merge this - it is just interfaces. However, I would like to think about interfaces before taking the time to implement.\r\n\r\nThe idea here is that (almost) all recommendation operations return a *result set*: a (possibly ordered) map of item (or user, for finding related users) IDs to values. Individual algorithms can extend the result set to provide additional details (see [DetailedResults](//github.com/lenskit/lenskit/wiki/DetailedResults)).\r\n\r\nFor recommendation, the result set will be ordered in decreasing order of score.\r\n\r\nThis subsumes both `SparseVector` and `List<ScoredId>` for recommendation and prediction results.","created_at":"2015-05-21T20:21:01Z","updated_at":"2015-05-27T19:31:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e4e69de36a14b74a37b8b7cba3832cbc2d5e93c0","assignee":{"login":"kluver","id":5695556,"avatar_url":"https://avatars.githubusercontent.com/u/5695556?v=3","gravatar_id":"","url":"https://api.github.com/users/kluver","html_url":"https://github.com/kluver","followers_url":"https://api.github.com/users/kluver/followers","following_url":"https://api.github.com/users/kluver/following{/other_user}","gists_url":"https://api.github.com/users/kluver/gists{/gist_id}","starred_url":"https://api.github.com/users/kluver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kluver/subscriptions","organizations_url":"https://api.github.com/users/kluver/orgs","repos_url":"https://api.github.com/users/kluver/repos","events_url":"https://api.github.com/users/kluver/events{/privacy}","received_events_url":"https://api.github.com/users/kluver/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/lenskit/lenskit/milestones/23","html_url":"https://github.com/lenskit/lenskit/milestones/3.0","labels_url":"https://api.github.com/repos/lenskit/lenskit/milestones/23/labels","id":433278,"number":23,"title":"3.0","description":"LensKit 3.0, upcoming major change + long-term stable version.","creator":null,"open_issues":55,"closed_issues":22,"state":"open","created_at":"2013-09-21T00:54:48Z","updated_at":"2015-05-21T21:43:59Z","due_on":"2015-07-31T05:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733/commits","review_comments_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733/comments","review_comment_url":"https://api.github.com/repos/lenskit/lenskit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lenskit/lenskit/issues/733/comments","statuses_url":"https://api.github.com/repos/lenskit/lenskit/statuses/29235871ee6c8bcf883333eab60edd9818585021","head":{"label":"mdekstrand:feature/727-result-api","ref":"feature/727-result-api","sha":"29235871ee6c8bcf883333eab60edd9818585021","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"repo":{"id":12954960,"name":"lenskit","full_name":"mdekstrand/lenskit","owner":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mdekstrand/lenskit","description":"LensKit recommender toolkit (Michael's work-in-progress fork, feature branches may be rebased).","fork":true,"url":"https://api.github.com/repos/mdekstrand/lenskit","forks_url":"https://api.github.com/repos/mdekstrand/lenskit/forks","keys_url":"https://api.github.com/repos/mdekstrand/lenskit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mdekstrand/lenskit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mdekstrand/lenskit/teams","hooks_url":"https://api.github.com/repos/mdekstrand/lenskit/hooks","issue_events_url":"https://api.github.com/repos/mdekstrand/lenskit/issues/events{/number}","events_url":"https://api.github.com/repos/mdekstrand/lenskit/events","assignees_url":"https://api.github.com/repos/mdekstrand/lenskit/assignees{/user}","branches_url":"https://api.github.com/repos/mdekstrand/lenskit/branches{/branch}","tags_url":"https://api.github.com/repos/mdekstrand/lenskit/tags","blobs_url":"https://api.github.com/repos/mdekstrand/lenskit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mdekstrand/lenskit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mdekstrand/lenskit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mdekstrand/lenskit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mdekstrand/lenskit/statuses/{sha}","languages_url":"https://api.github.com/repos/mdekstrand/lenskit/languages","stargazers_url":"https://api.github.com/repos/mdekstrand/lenskit/stargazers","contributors_url":"https://api.github.com/repos/mdekstrand/lenskit/contributors","subscribers_url":"https://api.github.com/repos/mdekstrand/lenskit/subscribers","subscription_url":"https://api.github.com/repos/mdekstrand/lenskit/subscription","commits_url":"https://api.github.com/repos/mdekstrand/lenskit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mdekstrand/lenskit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mdekstrand/lenskit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mdekstrand/lenskit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mdekstrand/lenskit/contents/{+path}","compare_url":"https://api.github.com/repos/mdekstrand/lenskit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mdekstrand/lenskit/merges","archive_url":"https://api.github.com/repos/mdekstrand/lenskit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mdekstrand/lenskit/downloads","issues_url":"https://api.github.com/repos/mdekstrand/lenskit/issues{/number}","pulls_url":"https://api.github.com/repos/mdekstrand/lenskit/pulls{/number}","milestones_url":"https://api.github.com/repos/mdekstrand/lenskit/milestones{/number}","notifications_url":"https://api.github.com/repos/mdekstrand/lenskit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mdekstrand/lenskit/labels{/name}","releases_url":"https://api.github.com/repos/mdekstrand/lenskit/releases{/id}","created_at":"2013-09-19T17:41:33Z","updated_at":"2015-05-05T20:43:43Z","pushed_at":"2015-05-27T17:37:29Z","git_url":"git://github.com/mdekstrand/lenskit.git","ssh_url":"git@github.com:mdekstrand/lenskit.git","clone_url":"https://github.com/mdekstrand/lenskit.git","svn_url":"https://github.com/mdekstrand/lenskit","homepage":"","size":21255,"stargazers_count":0,"watchers_count":0,"language":"Java","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":"lenskit:master","ref":"master","sha":"cc91d3f44074b2fa9c6169ee831d64891e041018","user":{"login":"lenskit","id":7562892,"avatar_url":"https://avatars.githubusercontent.com/u/7562892?v=3","gravatar_id":"","url":"https://api.github.com/users/lenskit","html_url":"https://github.com/lenskit","followers_url":"https://api.github.com/users/lenskit/followers","following_url":"https://api.github.com/users/lenskit/following{/other_user}","gists_url":"https://api.github.com/users/lenskit/gists{/gist_id}","starred_url":"https://api.github.com/users/lenskit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lenskit/subscriptions","organizations_url":"https://api.github.com/users/lenskit/orgs","repos_url":"https://api.github.com/users/lenskit/repos","events_url":"https://api.github.com/users/lenskit/events{/privacy}","received_events_url":"https://api.github.com/users/lenskit/received_events","type":"Organization","site_admin":false},"repo":{"id":12953256,"name":"lenskit","full_name":"lenskit/lenskit","owner":{"login":"lenskit","id":7562892,"avatar_url":"https://avatars.githubusercontent.com/u/7562892?v=3","gravatar_id":"","url":"https://api.github.com/users/lenskit","html_url":"https://github.com/lenskit","followers_url":"https://api.github.com/users/lenskit/followers","following_url":"https://api.github.com/users/lenskit/following{/other_user}","gists_url":"https://api.github.com/users/lenskit/gists{/gist_id}","starred_url":"https://api.github.com/users/lenskit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lenskit/subscriptions","organizations_url":"https://api.github.com/users/lenskit/orgs","repos_url":"https://api.github.com/users/lenskit/repos","events_url":"https://api.github.com/users/lenskit/events{/privacy}","received_events_url":"https://api.github.com/users/lenskit/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lenskit/lenskit","description":"LensKit recommender toolkit.","fork":false,"url":"https://api.github.com/repos/lenskit/lenskit","forks_url":"https://api.github.com/repos/lenskit/lenskit/forks","keys_url":"https://api.github.com/repos/lenskit/lenskit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lenskit/lenskit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lenskit/lenskit/teams","hooks_url":"https://api.github.com/repos/lenskit/lenskit/hooks","issue_events_url":"https://api.github.com/repos/lenskit/lenskit/issues/events{/number}","events_url":"https://api.github.com/repos/lenskit/lenskit/events","assignees_url":"https://api.github.com/repos/lenskit/lenskit/assignees{/user}","branches_url":"https://api.github.com/repos/lenskit/lenskit/branches{/branch}","tags_url":"https://api.github.com/repos/lenskit/lenskit/tags","blobs_url":"https://api.github.com/repos/lenskit/lenskit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lenskit/lenskit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lenskit/lenskit/git/refs{/sha}","trees_url":"https://api.github.com/repos/lenskit/lenskit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lenskit/lenskit/statuses/{sha}","languages_url":"https://api.github.com/repos/lenskit/lenskit/languages","stargazers_url":"https://api.github.com/repos/lenskit/lenskit/stargazers","contributors_url":"https://api.github.com/repos/lenskit/lenskit/contributors","subscribers_url":"https://api.github.com/repos/lenskit/lenskit/subscribers","subscription_url":"https://api.github.com/repos/lenskit/lenskit/subscription","commits_url":"https://api.github.com/repos/lenskit/lenskit/commits{/sha}","git_commits_url":"https://api.github.com/repos/lenskit/lenskit/git/commits{/sha}","comments_url":"https://api.github.com/repos/lenskit/lenskit/comments{/number}","issue_comment_url":"https://api.github.com/repos/lenskit/lenskit/issues/comments{/number}","contents_url":"https://api.github.com/repos/lenskit/lenskit/contents/{+path}","compare_url":"https://api.github.com/repos/lenskit/lenskit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lenskit/lenskit/merges","archive_url":"https://api.github.com/repos/lenskit/lenskit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lenskit/lenskit/downloads","issues_url":"https://api.github.com/repos/lenskit/lenskit/issues{/number}","pulls_url":"https://api.github.com/repos/lenskit/lenskit/pulls{/number}","milestones_url":"https://api.github.com/repos/lenskit/lenskit/milestones{/number}","notifications_url":"https://api.github.com/repos/lenskit/lenskit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lenskit/lenskit/labels{/name}","releases_url":"https://api.github.com/repos/lenskit/lenskit/releases{/id}","created_at":"2013-09-19T16:19:33Z","updated_at":"2015-05-27T00:45:25Z","pushed_at":"2015-05-27T17:37:30Z","git_url":"git://github.com/lenskit/lenskit.git","ssh_url":"git@github.com:lenskit/lenskit.git","clone_url":"https://github.com/lenskit/lenskit.git","svn_url":"https://github.com/lenskit/lenskit","homepage":"http://lenskit.grouplens.org","size":25747,"stargazers_count":307,"watchers_count":307,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":137,"mirror_url":null,"open_issues_count":120,"forks":137,"open_issues":120,"watchers":307,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733"},"html":{"href":"https://github.com/lenskit/lenskit/pull/733"},"issue":{"href":"https://api.github.com/repos/lenskit/lenskit/issues/733"},"comments":{"href":"https://api.github.com/repos/lenskit/lenskit/issues/733/comments"},"review_comments":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733/comments"},"review_comment":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733/commits"},"statuses":{"href":"https://api.github.com/repos/lenskit/lenskit/statuses/29235871ee6c8bcf883333eab60edd9818585021"}}}}