{"action":"created","issue":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/635","repository_url":"https://api.github.com/repos/ocaml/ocaml","labels_url":"https://api.github.com/repos/ocaml/ocaml/issues/635/labels{/name}","comments_url":"https://api.github.com/repos/ocaml/ocaml/issues/635/comments","events_url":"https://api.github.com/repos/ocaml/ocaml/issues/635/events","html_url":"https://github.com/ocaml/ocaml/pull/635","id":162294766,"number":635,"title":"add iterators to most containers in stdlib","user":{"login":"c-cube","id":1274291,"avatar_url":"https://avatars.githubusercontent.com/u/1274291?v=3","gravatar_id":"","url":"https://api.github.com/users/c-cube","html_url":"https://github.com/c-cube","followers_url":"https://api.github.com/users/c-cube/followers","following_url":"https://api.github.com/users/c-cube/following{/other_user}","gists_url":"https://api.github.com/users/c-cube/gists{/gist_id}","starred_url":"https://api.github.com/users/c-cube/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/c-cube/subscriptions","organizations_url":"https://api.github.com/users/c-cube/orgs","repos_url":"https://api.github.com/users/c-cube/repos","events_url":"https://api.github.com/users/c-cube/events{/privacy}","received_events_url":"https://api.github.com/users/c-cube/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ocaml/ocaml/labels/stdlib","name":"stdlib","color":"fbca04"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-06-25T18:56:02Z","updated_at":"2016-06-25T20:40:11Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ocaml/ocaml/pulls/635","html_url":"https://github.com/ocaml/ocaml/pull/635","diff_url":"https://github.com/ocaml/ocaml/pull/635.diff","patch_url":"https://github.com/ocaml/ocaml/pull/635.patch"},"body":"Following the new guidelines, here is the first of a series of proposals to improve and extend the stdlib.\r\n\r\nI think iterators should be available in the stdlib for several of the reasons mentionned in the guidelines:\r\n\r\n- \"they cannot easily be implemented externally\": if I don't have access to the internals of `Map`, `Stack` or `Hashtbl`, I cannot implement proper iterators on them;\r\n- \"they facilitate communication between independent external libraries\": having iterators makes it easier to transfer data between various data structures by just providing two functions (from/to). \r\n\r\n## Testing\r\n\r\nThere are no tests right now, because it's not clear to me how to test those. I already have some tests using [qtest](https://github.com/vincent-hugot/iTeML), but that relies on 3rd party tools. I think tests using expect/result files are overkill, so we probably should have a small unit/random testing lib in the compiler? I will obviously upgrade this PR once the proper way of testing becomes clear. \r\n\r\n## The iterator type\r\n\r\nI have been involved in discussions with Janestreet, @dbuenzli and others to try to agree on a common iterator type (batteries/extlib have `Enum`, JST has `Core.Sequence`, I use `sequence`, etc.). We did not reach an agreement, in parts because of performance considerations related to flambda. I still think the solution I propose, `type 'a gen = unit -> 'a option`, is the best tradeoff:\r\n\r\n- it is simple, and easy to implement;\r\n- it is structural, making compatibility between libraries trivial (just declare it; no need for a `result`/`bytes` compatibility package);\r\n- it looks a lot like iterators in many other languages, including python, java, C#, rust, etc. and therefore should be familiar to many programmers;\r\n- there already is an extensive [library of combinators](https://github.com/c-cube/gen/) for it, demonstrating that it is indeed possible to implement many operations on it;\r\n- it has good performance, even with flambda (see benchmark results for 4.03 and 4.03+flambda below); the much faster iterators (sequence and fold) are less expressive, and cannot express `zip`, `merge`, `map2` and the likes. In contrast, `gen` can be used for consuming an iterator step by step.\r\n\r\nhttps://github.com/c-cube/iterators_bench/blob/master/res_4.03\r\nhttps://github.com/c-cube/iterators_bench/blob/master/res_4.03_flambda\r\n\r\n## Other planned proposals:\r\n\r\n(as a mere preview ;)\r\n\r\n- a module for options (map, flat_map, etc. really \"fill obvious gaps\", as in, they are useful in every single OCaml program).\r\n- ideally, I'd like a module `IO` in which channel-related functions could go, but they already belong in pervasives, so this ship probably has sailed. Nevertheless, I'd like to add some functions that promote a safe handling of resources, in the vein of `val with_file_in : string -> (in_channel -> 'a) -> 'a` (taking care of always closing the file); also, some idiom to iterate on the lines in a channel, read a whole channel into a string, and other basics that get reinvented hundreds of times in the community.\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/comments/228569505","html_url":"https://github.com/ocaml/ocaml/pull/635#issuecomment-228569505","issue_url":"https://api.github.com/repos/ocaml/ocaml/issues/635","id":228569505,"user":{"login":"Drup","id":801124,"avatar_url":"https://avatars.githubusercontent.com/u/801124?v=3","gravatar_id":"","url":"https://api.github.com/users/Drup","html_url":"https://github.com/Drup","followers_url":"https://api.github.com/users/Drup/followers","following_url":"https://api.github.com/users/Drup/following{/other_user}","gists_url":"https://api.github.com/users/Drup/gists{/gist_id}","starred_url":"https://api.github.com/users/Drup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Drup/subscriptions","organizations_url":"https://api.github.com/users/Drup/orgs","repos_url":"https://api.github.com/users/Drup/repos","events_url":"https://api.github.com/users/Drup/events{/privacy}","received_events_url":"https://api.github.com/users/Drup/received_events","type":"User","site_admin":false},"created_at":"2016-06-25T20:40:11Z","updated_at":"2016-06-25T20:40:11Z","body":"To complement @gasche's point, `sequence` does not strictly need further support from the `stdlib`. All datastructure have an `iter` function, which is equivalent to `to_sequence`.\r\n\r\nI have been using those two style of iterators for a while now, I think they are very useful and covers all my usecases. Having the various `gen` functions directly in the stdlib (and hopefully a standardization in the OCaml ecosystem) would be extremely valuable."}}
{"actor":{"display_login":"Drup"}}