Re: Proposal: make Glib::KeyFile easier to use

2013-12-27 Thread Aurimas Cernius
-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

2013-12-27 Thread Povilas Kanapickas
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

2013-12-26 Thread Aurimas Cernius
-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

2013-12-26 Thread Povilas Kanapickas
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

2013-12-26 Thread Aurimas Cernius
-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

2013-12-26 Thread Povilas Kanapickas
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

2013-12-26 Thread Aurimas Cernius
-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

2013-12-26 Thread Povilas Kanapickas
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

2013-12-25 Thread Yann LEYDIER

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