{"action":"created","issue":{"url":"https://api.github.com/repos/indigits/scirust/issues/25","labels_url":"https://api.github.com/repos/indigits/scirust/issues/25/labels{/name}","comments_url":"https://api.github.com/repos/indigits/scirust/issues/25/comments","events_url":"https://api.github.com/repos/indigits/scirust/issues/25/events","html_url":"https://github.com/indigits/scirust/issues/25","id":100165054,"number":25,"title":"RFC: a convention for error handling","user":{"login":"shailesh1729","id":8783308,"avatar_url":"https://avatars.githubusercontent.com/u/8783308?v=3","gravatar_id":"","url":"https://api.github.com/users/shailesh1729","html_url":"https://github.com/shailesh1729","followers_url":"https://api.github.com/users/shailesh1729/followers","following_url":"https://api.github.com/users/shailesh1729/following{/other_user}","gists_url":"https://api.github.com/users/shailesh1729/gists{/gist_id}","starred_url":"https://api.github.com/users/shailesh1729/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shailesh1729/subscriptions","organizations_url":"https://api.github.com/users/shailesh1729/orgs","repos_url":"https://api.github.com/users/shailesh1729/repos","events_url":"https://api.github.com/users/shailesh1729/events{/privacy}","received_events_url":"https://api.github.com/users/shailesh1729/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/indigits/scirust/labels/RFC","name":"RFC","color":"eb6420"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-08-10T20:46:27Z","updated_at":"2015-08-11T11:42:04Z","closed_at":null,"body":"This RFC proposes a convention for structuring methods in SciRust \r\nwhich can cater to the conflicting needs of efficiency, easy of use\r\nand effective error handling.\r\n\r\nFor the impatient: \r\n\r\n    // Efficient access without bound checks\r\n    unsafe fn get_unchecked(&self, r : usize, c : usize) -> T;\r\n    // Safe access with bound checks, raises error if invalid address\r\n    fn get_checked(&self, r : usize, c : usize) -> Result<T, Error>;\r\n    // User friendly version. Panics in case of error\r\n    fn get(&self, r : usize, c : usize) -> T;\r\n\r\n    // Efficient modification without bound checks\r\n    unsafe fn set_unchecked(&mut self, r : usize, c : usize, value : T);\r\n\r\n    // Safe modification with bound check\r\n    fn set(&mut self, r : usize, c : usize, value : T);\r\n\r\n\r\n# Detailed discussion\r\n\r\nThe audience of SciRust can be possibly divided into\r\ntwo usage scenarios.\r\n\r\n* A script style usage, where the objective is to quickly\r\n  do some numerical experiment, get the results and analyze them.\r\n* A library development usage, where more professional libraries\r\n  would be built on top of fundamental building blocks provided\r\n  by SciRust (these may be other modules shipped in SciRust itself).\r\n\r\nWhile the first usage scenario is important for getting new users hooked\r\nto the library, the second usage scenario is also important for justifying\r\nwhy Rust should be used for scientific software development compared\r\nto other scientific computing platforms.\r\n\r\n\r\nIn context of the two usage scenarios, the design of SciRust has three conflicting goals:\r\n\r\n* Ease of use\r\n* Efficiency\r\n* Well managed error handling\r\n\r\nWhile ease of use is important for script style usage,\r\nefficiency and well managed error handling are important\r\nfor serious software development on top of core components\r\nprovided by SciRust.\r\n\r\n\r\nWe will consider the example of a ```get(r,c)``` method\r\non a matrix object to discuss these conflicting goals.\r\nPlease note that ```get``` is just a representative method\r\nfor this discussion. The design ideas can be applied in\r\nmany different parts of SciRust once accepted.\r\n\r\nIf ```get``` is being called in a loop, usually the code\r\naround it can ensure that the conditions for accessing\r\ndata within the boundary of the matrix are met correctly.\r\nThus, a bound checking within the implementation of ```get```\r\nis just an extra overhead. \r\n\r\nWhile this design is good for writing efficient software,\r\nit can lead to a number of memory related bugs and goes\r\nagainst the fundamental philosophy of Rust (Safety first).\r\nThere are actually two different options for error handling:\r\n\r\n* Returning either ```Option<T>``` or ```Result<T, Error>```.\r\n* Using the ```panic``` mechanism.\r\n\r\n```Option<T>``` or ```Result<T, Error>``` provides the users a\r\nfine grained control over what to do when an error occurs.\r\nThis is certainly the Rusty way of doing things. At the\r\nsame time, both of these return types make the user code\r\nmore complicated. One has to add extra calls to ```.unwrap()```\r\neven if one is sure that the function is not going to fail.\r\n\r\n\r\nUsers of scientific computing tend to prefer an environment\r\nwhere they can get more work done with less effort. This is\r\na reason of the success of specialized environments like\r\nMATLAB. Open source environments like Python (NumPy, SciPy)\r\ntry to achieve something similar.\r\n\r\nWhile SciRust doesn't intend to compete at the level of \r\nsimplicity provided by MATLAB/Python environments, it does\r\nintend to take an extra effort wherever possible to address\r\nthe ease of use goal.  \r\nIn this context,  the return type of a ```getter``` should\r\nbe just the value type ```T```. This can be achieved\r\nsafely by using a panic if the access boundary \r\nconditions are not met.\r\n\r\n\r\nThe discussion above suggests up to 3 possible ways of \r\nimplementing methods like ```get```.\r\n\r\n* An unchecked (and unsafe) version for high efficiency code\r\n  where the calling code is responsible for ensuring that\r\n  the necessary requirements for correct execution of the \r\n  method are being met.\r\n\r\n* A safe version which returns either ```Option<T>``` or\r\n  ```Result<T, Error>``` which can be used for professional\r\n  software development where the calling code has full control\r\n  over error handling.\r\n  \r\n* Another safe version which panics in case of error but provides\r\n  an API which is simpler to use for writing short scientific\r\n  computing scripts.\r\n\r\n# Proposed convention\r\n\r\nWe propose that a method for which these variations \r\nneed to be supported, should follow the convention defined below:\r\n\r\n* A ```method_unchecked``` version should provide basic implementation\r\n  of the method. This should assume that necessary conditions\r\n  for successful execution of the methods are already being\r\n  ensured by the calling code. The unchecked version of method\r\n  MUST be marked ```unsafe```. This ensures that the calling code\r\n  knows that it is responsible for ensuring the right conditions\r\n  for calling the unchecked method.\r\n\r\n* A ```method_checked``` version should be implemented on top of\r\n  a ```method_unchecked``` method. The checked version should\r\n  check for all the requirements for calling the method safely.\r\n  The return type should be either ```Option<T>``` or\r\n  ```Result<T, Error>```. In case the required conditions for\r\n  calling the method are not met, a ```None``` or ```Error```\r\n  should be returned. Once the required conditions are met, \r\n  ```method_unchecked``` should be called to get the result\r\n  which would be wrapped inside ```Option``` or ```Result```.\r\n\r\n* A ```method``` version should be built on top of ```method_checked``` version. \r\n  It should simply attempt to unwrap\r\n  the value returned by ```method_checked``` and return as ```T```.\r\n  If ```method_checked``` returns an error or None, this version\r\n  should panic.\r\n\r\nFirst two versions are suitable for professional development\r\nwhere most of the time we need a safe API while at some times\r\nwe need an unsafe API for efficient implementation.\r\nThe third version is suitable for script style usage scenario.\r\n\r\nThe convention has been illustrated in the three versions of\r\n```get``` at the beginning of this document.\r\n\r\n\r\n# API bloat\r\n\r\nWhile this convention is expected to lead into an API bloat,\r\nbut if the convention is followed properly across the library,\r\nthen it should be easy to follow (both from the perspective\r\nof users of the library and from the perspective of developers\r\nof the library).\r\n\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/indigits/scirust/issues/comments/129847314","html_url":"https://github.com/indigits/scirust/issues/25#issuecomment-129847314","issue_url":"https://api.github.com/repos/indigits/scirust/issues/25","id":129847314,"user":{"login":"shailesh1729","id":8783308,"avatar_url":"https://avatars.githubusercontent.com/u/8783308?v=3","gravatar_id":"","url":"https://api.github.com/users/shailesh1729","html_url":"https://github.com/shailesh1729","followers_url":"https://api.github.com/users/shailesh1729/followers","following_url":"https://api.github.com/users/shailesh1729/following{/other_user}","gists_url":"https://api.github.com/users/shailesh1729/gists{/gist_id}","starred_url":"https://api.github.com/users/shailesh1729/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shailesh1729/subscriptions","organizations_url":"https://api.github.com/users/shailesh1729/orgs","repos_url":"https://api.github.com/users/shailesh1729/repos","events_url":"https://api.github.com/users/shailesh1729/events{/privacy}","received_events_url":"https://api.github.com/users/shailesh1729/received_events","type":"User","site_admin":false},"created_at":"2015-08-11T11:42:03Z","updated_at":"2015-08-11T11:42:03Z","body":"Rust slices have both get_unchecked() and get() methods. https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked . The proposed design is not very different. But rather than having 2 versions of get, here 3 versions are being suggested. The panic version is meant primarily for making writing scripty code easier. "}}