Re: Proposal: make Glib::KeyFile easier to use
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, try { fun(f.get_integer(a, b)); } catch(Glib::KeyFileError ) { /* Not found or not parsed */ } That's not an equivalent. I've written my code carefully to expose what The only case it is not equivalent is if Glib::KeyFileError can be thrown inside fun(), which would mean you're reading key file there too... it takes to solve the issue properly. The rewritten code, while being short, has the following two subtle issues: * Exceptions are used for the main control flow. That is, an exception will be thrown whenever an optional key is not present. Since this is not unexpected failure mode, it should not be handled via an exception. I disagree. Expected failure is still a failure and can drop code execution to error handling code. Reporting potentially non-fatal error as exception is not ideal of course, but definitely possible. If missing or non-parsable key falls back to the same code, it is actually a good thing they both throw the same exception. The same way, if non-parsable key throws exception, it's meaningful for non-existing key to throw too (though I'd like more to pass default value as additional argument). * I catch the exceptions that originate out of fun() too. While it is unlikely that it may throw Glib::KeyFileError, this approach is semantically wrong. Any bugs caused by this would be extremely hard to fix. As long as fun() does not throw Glib::KeyFileError, everything is fine - - a written catch only handles this type of exception, all other types are handled by enclosing try-catch. I don't see what is semantically wrong and so error-prone with this. Besides, reading about boost optional http://www.boost.org/doc/libs/1_55_0/libs/optional/doc/html/index.html I think KeyFile is somewhat in the middle between (A) and (C). Throwing exception when key is unparsable is reasonable. When key is missing, I'd expect most cases to be the same as with unparsable, the remaining one can check for key existence. So really, I see no advantage of optional idiom for key file. - -- Aurimas -BEGIN PGP SIGNATURE- Version: GnuPG v1 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSvdgLAAoJECtTeRAzEaLP8RgIAJrUHDvdYeoVvdx1keoqaFew 2LnFQvMhtFvElZ/QwSpnwwZHP3vbjjpKc4DxQ7LtCU5P0CNw7dcYv2lvi4NQnnRN 5yprj5BxqpeZAnOUakfJo8DqNW9h6MAGnci3OVNUG/Ff7wzNQxBMWEccb7CxHn0H X9gLepyR87emosXVaZa4t1RdIOrP6RlgxC+kTigzl4SRKa6uFr1q65V2TNK/IDX+ g5n8yBGLXxliJxu/qMQX9+WATqmm1SPTaUKLm7aSMGOZhdC9snug0p4Ok8owWirQ vBiVD6HHRYIivYfFkAG6j9WPzbOTZSo4yIo6dmuiIqG9OgaLgSb9pl3WzTrSd08= =ycD5 -END PGP SIGNATURE- ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
On 12/27/2013 09:42 PM, Aurimas Cernius wrote: Expected failure is still a failure and can drop code execution to error handling code. Reporting potentially non-fatal error as exception is not ideal of course, but definitely possible. I can't agree with you on this point. Using exceptions for expected failures is simply wrong; it is an widely recognized anti-pattern. It's not an accident all prominent C++ experts advice against this practice. Plenty of rationale is singel Google query away, e.g. [1][2][3][4]. If you want, you can find a lot more. [1]: c2.com/cgi/wiki?DontUseExceptionsForFlowControl [2]: stackoverflow.com/questions/1744070 [3]: stackoverflow.com/questions/729379 [4]: programmers.stackexchange.com/questions/189222 Regards, Povilas ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, The current interface of Glib::KeyFile::get_* functions is quite inconvenient as exceptions are the only reliable way to receive error conditions. Consider the following example: Glib::KeyFile f; ... int x = f.get_integer(a, b); // (1) There are two possible error conditions that may cause (1) to fail: * there's no key b in group a * the value of the key b in group a is not an integer One external thing to consider here is who edits key files. I don't expect non-pro guy doing anything there, so key files probably are unlikely to be broken (low probability). Whereas the former condition can be checked for via KeyFile::has_key, to check for the latter, one has only the following two options: * catch the thrown exception * get the value via get_string and use a separate function to parse it Both of these approaches are not optimal. I think the situation could be improved. My proposal is as follows: * A new class template Glib::OptionalT is created. The new class template would be identical to boost::optional[1]. * A new family of functions for reading a keyfile is created (say, for example, get_*_opt). The new functions would return Glib::OptionalT instead of T. All error conditions would be reported by returning 'empty' optional object. The new functions would not throw any exceptions on any circumstances. This would allow much simpler usage of the API. For example: Glib::KeyFile f; ... auto opt = f.get_integer_opt(a, b); // let's say we can use C++11 if (opt) { // utilize the value in *opt int r = *opt; ... } Do think that if is more convenient that try-catch? I'm not sure about that. If you think of more convenient getter for key, I'd think of passing default value as last argument, that would be returned in case key is missing or not valid. I think that would cover most of the cases, the remaining few could deal with exceptions. - -- Aurimas -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSvH3sAAoJECtTeRAzEaLP3EEH+gJFPEZYwcV77j7/v0L7olAa /YXt1IUxZrHU+qKLAeXUSCOopP0XHNfQdAjEmOCYgjbkx/FD2gW4wYhZqvSFH/4o hfQ2r5hAgGTsqubzH3fMxPr0znONsTJyOE7vrBR9hsITQBjezb5iGLDH6sRex1Xl rrp9QRttZSO/h+hrjpTAWRRm5tZvN7EhUyYC8hcu/kdFlTwN+XALw0gkDTim271v iO/TaqumBQoIx7oOU8u8czrQ1Ay7nujxRLuxHptm4707RTi7pa7qdc0NEEXExK7Z KerSm9NRBcPMM7BpohKDP0uYdvFQOu8xzfSVz1DxddbabtD4y4GDhZDP8eqUrJk= =gTsV -END PGP SIGNATURE- ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
On 12/26/2013 09:05 PM, Aurimas Cernius wrote: Hi, The current interface of Glib::KeyFile::get_* functions is quite inconvenient as exceptions are the only reliable way to receive error conditions. Consider the following example: Glib::KeyFile f; ... int x = f.get_integer(a, b); // (1) There are two possible error conditions that may cause (1) to fail: * there's no key b in group a * the value of the key b in group a is not an integer One external thing to consider here is who edits key files. I don't expect non-pro guy doing anything there, so key files probably are unlikely to be broken (low probability). Yes, but I still don't want stack unwinding to occur. In my use case the rest of the key file must still be read successfully. If it was possible to give up on errors I would move error handling somewhere higher up in the call stack and use exceptions. Whereas the former condition can be checked for via KeyFile::has_key, to check for the latter, one has only the following two options: * catch the thrown exception * get the value via get_string and use a separate function to parse it Both of these approaches are not optimal. I think the situation could be improved. My proposal is as follows: * A new class template Glib::OptionalT is created. The new class template would be identical to boost::optional[1]. * A new family of functions for reading a keyfile is created (say, for example, get_*_opt). The new functions would return Glib::OptionalT instead of T. All error conditions would be reported by returning 'empty' optional object. The new functions would not throw any exceptions on any circumstances. This would allow much simpler usage of the API. For example: Glib::KeyFile f; ... auto opt = f.get_integer_opt(a, b); // let's say we can use C++11 if (opt) { // utilize the value in *opt int r = *opt; ... } Do think that if is more convenient that try-catch? I'm not sure about that. If you think of more convenient getter for key, I'd think of passing default value as last argument, that would be returned in case key is missing or not valid. I think that would cover most of the cases, the remaining few could deal with exceptions. Yes, I think that a simple conditional is a better approach in this specific use-case: * Using exceptions to rewind the stack by one level is fundamentally wrong. One can do that, but that's not idiomatic C++. * Using a default value is not workable when the range of input data must not be reduced (which is one of my requirements). Regards, Povilas ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, One external thing to consider here is who edits key files. I don't expect non-pro guy doing anything there, so key files probably are unlikely to be broken (low probability). Yes, but I still don't want stack unwinding to occur. In my use case the rest of the key file must still be read successfully. If it was possible to give up on errors I would move error handling somewhere higher up in the call stack and use exceptions. You can wrap every individual call to get_* with try-catch (write your own helper function for this). Should such convenience method be part of Glibmm itself is a debate, of course. Do think that if is more convenient that try-catch? I'm not sure about that. If you think of more convenient getter for key, I'd think of passing default value as last argument, that would be returned in case key is missing or not valid. I think that would cover most of the cases, the remaining few could deal with exceptions. Yes, I think that a simple conditional is a better approach in this specific use-case: * Using exceptions to rewind the stack by one level is fundamentally wrong. One can do that, but that's not idiomatic C++. No, that's what exceptions were designed for. What is wrong is wrapping every statement in try-catch. * Using a default value is not workable when the range of input data must not be reduced (which is one of my requirements). I don't quite understand what you're trying to achieve. Your point is to make Glib::KeyFile easier to use, but I don't really see, how your proposal achieves that. Returning a wrapper object and writing if to check it's value does not seem to be easier than wrapping a call in try-catch: int val; try { val = key_file.get_integer(a, b); } catch(Glib::KeyFileError ) { val = 0; // let this be default value } int val; auto opt = f.get_integer_opt(a, b); if(opt) { val = *opt; } else { val = 0; // let this be default value } As you can see, your proposal in my case result in more code. Can you present a use-case, where it makes things easier? - -- Aurimas -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSvJJjAAoJECtTeRAzEaLPFiwH/j4XGOvlJNfhU+u4Vng2FDI1 rRlHd2oQQLxbYNGPPvMdWxfThxKWQHLnhsbuvswO4APOXXO3xu92YlmapUNUdrkM IVsOjq8soWluUH9ZYOAOq6JCDqorN+yd481ZiMgyOIw1GRcABQUsIEqVjkYC6euD RHgVnHWIoE1+OsAY6hWuN/uv8aJ/SqQ4WnsrNIlH5gALRAuEfGs2kPBH0o6emIia rOXjwPCYfkb4hYGhoS3wdq52y7Xjn+siN8VhvL7JNxFr/49xZZuXd5f6mXhjSXar +MEc4QLUuHu1r7zjx/cP/s2cwjWHhS2Mc52zLxBOfW+d5rVp8HMqXO63xObSmkA= =Mqfq -END PGP SIGNATURE- ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
On 12/26/2013 10:32 PM, Aurimas Cernius wrote: ... I don't quite understand what you're trying to achieve. Your point is to make Glib::KeyFile easier to use, but I don't really see, how your proposal achieves that. Returning a wrapper object and writing if to check it's value does not seem to be easier than wrapping a call in try-catch: ... Okay. I think the following code that uses the current API illustrates my use case well: if (f.has_key(a, b) { // false is not unlikely bool parsed = false; int val; try { val = f.get_integer(a, b); parsed = true; } catch (...) { // unlikely } if (parsed) { fun(val); // fun() must called only if val is parsed // This is not necessarily a function } } else { /* no code, not unlikely */ } Two observations: * The keys are optional, thus exceptions can't be used to handle the case when a key is not present * fun() must not be called if the value has not been parsed correctly Regards, Povilas ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, Okay. I think the following code that uses the current API illustrates my use case well: if (f.has_key(a, b) { // false is not unlikely bool parsed = false; int val; try { val = f.get_integer(a, b); parsed = true; } catch (...) { // unlikely } if (parsed) { fun(val); // fun() must called only if val is parsed // This is not necessarily a function } } else { /* no code, not unlikely */ } Two observations: * The keys are optional, thus exceptions can't be used to handle the case when a key is not present * fun() must not be called if the value has not been parsed correctly But... this works just as you want with exceptions, if you rewrite code like this (I assume fun() to be a function here): try { fun(f.get_integer(a, b)); } catch(Glib::KeyFileError ) { /* Not found or not parsed */ } The same code using OptionalT would be: auto opt = f.get_integer(a, b); if(opt) { fun(*opt); } Honestly I don't see how the later is better/easier... Event if fun() is not a function but a bunch of code, it still looks pretty much the same. I look at all of this from practical POV: I want to write less/simpler code. Your proposal replaces exception by wrapper object, but I can't quickly think of a case where that would make code smaller or simpler, it just replaces one thing with another. Note: I'm not big fan of exceptions myself, so I'm not in defense of them. - -- Aurimas -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSvKjTAAoJECtTeRAzEaLPeVkH/2tcesphm5lGpB92ap6sQPJj LgNXz3Ykh42O4iOyNsPBXJjmLYpvG38BVsNK32alxj1BV+STQg3oyli25jiidC8N QM8k5b8gKR5/GvQU1tNyoxmus8ExXeDuCjz+PfKtd785kG5Wg1+Ugj5OP+bAPlkD MIyxR0HwAImHSV/MzdAPS+m0ZPJvsWRYB62oacfU+pMRzqJOP5ZPi7JAyPoNsnzK HUWzyhuiYVM5d/U5ToT6K0SSOMds9ubw/Im4eaxH8BM6Yv3htMk6FK3HBXTVKoaU orZmI7k9wmAkr3OQwW/0ALjeozkyizwLo4YZyTRdzhGydRe1fwgVbk71AtTQUrw= =gbfn -END PGP SIGNATURE- ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
On 12/27/2013 12:08 AM, Aurimas Cernius wrote: Hi, Okay. I think the following code that uses the current API illustrates my use case well: if (f.has_key(a, b) { // false is not unlikely bool parsed = false; int val; try { val = f.get_integer(a, b); parsed = true; } catch (...) { // unlikely } if (parsed) { fun(val); // fun() must called only if val is parsed // This is not necessarily a function } } else { /* no code, not unlikely */ } Two observations: * The keys are optional, thus exceptions can't be used to handle the case when a key is not present * fun() must not be called if the value has not been parsed correctly But... this works just as you want with exceptions, if you rewrite code like this (I assume fun() to be a function here): try { fun(f.get_integer(a, b)); } catch(Glib::KeyFileError ) { /* Not found or not parsed */ } That's not an equivalent. I've written my code carefully to expose what it takes to solve the issue properly. The rewritten code, while being short, has the following two subtle issues: * Exceptions are used for the main control flow. That is, an exception will be thrown whenever an optional key is not present. Since this is not unexpected failure mode, it should not be handled via an exception. * I catch the exceptions that originate out of fun() too. While it is unlikely that it may throw Glib::KeyFileError, this approach is semantically wrong. Any bugs caused by this would be extremely hard to fix. Regards, Povilas ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Proposal: make Glib::KeyFile easier to use
Hi, I think exceptions are the best to handle errors. They give more information than an Option and are as fast in recent versions of GCC. Moreover, semantically an Option is *not* an error. Finally, when reading someone else's code, a try/catch means that code can fail, whereas an Option means that the code might not return what the programmer had in mind (whatever he/she had in mind). For theses reasons, I'm glad Gtkmm uses exceptions to handle errors even if I have to write 3 lines of code instead of 1 to handle them. Regards, yann On 26/12/2013 00:39, Povilas Kanapickas wrote: Hello all, The current interface of Glib::KeyFile::get_* functions is quite inconvenient as exceptions are the only reliable way to receive error conditions. Consider the following example: Glib::KeyFile f; ... int x = f.get_integer(a, b); // (1) There are two possible error conditions that may cause (1) to fail: * there's no key b in group a * the value of the key b in group a is not an integer Whereas the former condition can be checked for via KeyFile::has_key, to check for the latter, one has only the following two options: * catch the thrown exception * get the value via get_string and use a separate function to parse it Both of these approaches are not optimal. I think the situation could be improved. My proposal is as follows: * A new class template Glib::OptionalT is created. The new class template would be identical to boost::optional[1]. * A new family of functions for reading a keyfile is created (say, for example, get_*_opt). The new functions would return Glib::OptionalT instead of T. All error conditions would be reported by returning 'empty' optional object. The new functions would not throw any exceptions on any circumstances. This would allow much simpler usage of the API. For example: Glib::KeyFile f; ... auto opt = f.get_integer_opt(a, b); // let's say we can use C++11 if (opt) { // utilize the value in *opt int r = *opt; ... } Note, that the conditional is not necessary. Trying to 'dereference' an empty optional object would throw an exception, so the behavior is pretty much the same as if using the 'old' get_integer function. Note, however, that the optional objects have value semantics, even though access to the stored value is done through overloaded operator* and operator-. It is likely that this is not the only case throughout Gtkmm, where a template similar to boost::optional would simplify the API. The idiom itself is very well known. It is almost a certainty that the C++ standard will include std::optional in 2017 or thereabouts (std::optional was going to be included into C++14, but minor problems with comparison operators caused it to be moved into a separate specification). Any opinions? I volunteer to implement the proposal, but before I begin, I would like to hear what do the maintainers think. Regards, Povilas [1]: http://www.boost.org/doc/libs/1_55_0/libs/optional/doc/html/index.html ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list