February 20, 2012
Why don't we use .tupleof for such a thing ?

Le 20/02/2012 20:17, Juan Manuel Cabo a écrit :
> I like the idea!
>
> Remember please for anyone reading: Use positional arguments in
> format strings. Otherwise:
>
> 	"The '%s' file's size is %d which is wrong"
>
>          translated to
>
> 	"El tamaño %d es incorrecto para el archivo %s"
>
> will be trouble. Instead please do:
>
>          "The '%1$s' file's size is %2$d which is wrong"
>
> specially for standard library messages. This would be very helpful!
>
> --jm
>
>
>
>> into this:
>>
>> try
>>      getopt(args, ...)
>> catch(Exception e)
>> {
>>      stderr.writeln(stringTemplate(typeid(e).toString(), e.info));
>>      return -1;
>> }
>>
>> The stringTemplate function loads the formatting template from a table indexed on typeid(e).toString() and formats it
>> with the info. It's simple factorization.
>>
>>
>> Andrei
>
>

February 20, 2012
> And so variant is the way to go ?
> 
> Clearly, this is a very strong arguement in favor of typed Exception, that provide usefull information about what went wrong. This is a safe approach.
> 
> Because this Variant stuff is going to require massive ducktyping of Exceptions, with all possible errors involved. The keys in the Variant[string] will depend on the Exception the dev is facing. This should be avoided and should warn us about the requirement of typed Exceptions.


Some of the things that characterize an exception, their traits, are transversal to any hierachy that you can imagine, now and in the future.

You can choose to keep changing a hierarchy, or build in some mechanism to the Exception base class, that will allow you to get your traits without downcasting.

Say that at your place of work the boss decides that all exception classes should have a COM error code, or that all exception classes should provide the URL of the request that generated it.

You know what will happen?

Your boss will require you to derive all your exception classes from COMException or from WebRequestException and then redefine FileNotFound as a subclass of them. So you will have your FileNotFoundException different than the standard library exception.

Don't believe me? It happened to .NET... they've got a COMException that wraps any other kind of error during a COM call.


--jm

February 20, 2012
On Monday, February 20, 2012 11:15:08 H. S. Teoh wrote:
> On Mon, Feb 20, 2012 at 01:52:15PM -0500, Jonathan M Davis wrote: [...]
> 
> > So, instead of
> > 
> > catch(SpecificException1 e)
> > {
> > 
> > //use fields specific to this exception to do whatever you need to do
> > 
> > }
> > catch(SpecificException2 e)
> > {
> > 
> > //use fields specific to this exception to do whatever you need to do
> > 
> > }
> > catch(GenericException e)
> > {
> > 
> > //handle the generic exception as best you can given the lack of //a specific one
> > 
> > }
> > 
> > you end up with something effectively along the lines of
> > 
> > catch(GenericException e)
> > {
> > 
> > if(/* e is SpecificException1 */)
> > {
> > //use fields specific to this exception to do whatever you need to do
> > }
> > else if(/* e is SpecificException2 */)
> > {
> > //use fields specific to this exception to do whatever you need to do
> > }
> > else
> > {
> > //handle the generic exception as best you can given the lack of
> > //a specific one
> > }
> > 
> > }
> 
> [...]
> 
> I think what Andrei wants to do is more along these lines:
> 
> catch(Exception e) {
> writeln(formatLocaleString(e.fmt, e.data));
> }
> 
> I think there's some merit to this idea. However, I'm still unsure about storing stuff in a Variant.

Except that if you're not printing out the message, if all of the data is in e.data as a variant, then you _do_ end up with code like I gave. The variant is a bad idea for anything trying to actually handle the exception rather than just print out a message.

> That's why I proposed to use runtime reflection to scan the exception object for applicable fields. Then you get the best of both worlds: the message formatter doesn't need to know what the fields are, and you get full compile-time type checking for catching code that directly accesses the fields.

That would certainly be better.

- Jonathan M Davis
February 20, 2012
So, if your boss wants the URL of the request that was made when the standard library threw you a FileNotFoundException, you can do:


	try {
	      ...
        } catch (Exception ex) {
                //Rethrow the exception with the added detail:
		ex.details["custom_url"] = getenv("URI");
                throw ex;
        }

(don't beat me if URI wasn't the envvar that apache sends for uri, I don't remember it at the moment).

--jm



On 02/20/2012 04:27 PM, Juan Manuel Cabo wrote:
>> And so variant is the way to go ?
>>
>> Clearly, this is a very strong arguement in favor of typed Exception, that provide usefull information about what went wrong. This is a safe approach.
>>
>> Because this Variant stuff is going to require massive ducktyping of Exceptions, with all possible errors involved. The keys in the Variant[string] will depend on the Exception the dev is facing. This should be avoided and should warn us about the requirement of typed Exceptions.
> 
> 
> Some of the things that characterize an exception, their traits, are transversal to any hierachy that you can imagine, now and in the future.
> 
> You can choose to keep changing a hierarchy, or build in some mechanism to the Exception base class, that will allow you to get your traits without downcasting.
> 
> Say that at your place of work the boss decides that all exception classes should have a COM error code, or that all exception classes should provide the URL of the request that generated it.
> 
> You know what will happen?
> 
> Your boss will require you to derive all your exception classes from COMException or from WebRequestException and then redefine FileNotFound as a subclass of them. So you will have your FileNotFoundException different than the standard library exception.
> 
> Don't believe me? It happened to .NET... they've got a COMException that wraps any other kind of error during a COM call.
> 
> 
> --jm
> 

February 20, 2012
On Mon, Feb 20, 2012 at 08:11:28PM +0100, deadalnix wrote: [...]
> Considering the handler, This would be great to see it as scoped. This imply using a scope delegate, and probably something as RAII to create it and delete it when we go out of scope.

Yeah, that definitely should be done, otherwise a handler installed by a function that's no longer in scope will still kick in when the same exception is triggered by unrelated code. That would be very bad.


> I'm more doubtfull about what can be done on the throw side. This need to be refined, and to be honnest, the idea is too new in my head to come up with something significant. The concept needs some decantation.
> 
> I wonder however, how to do something clean. The delegate will need some knowledge of the thrower onternal to do something really usefull, but then, we make the codebase more fragile (because the caler will depend on implementation of the calee, something that we want to avoid).

I've tried to do this by encapsulating the recovery options in the Condition object. So the delegate knows, here are the options I have of recovering, but it doesn't need to know how the low-level function implements those recovery strategies.

For example, the FileNotFoundCond object has a restart() method, and an inherited abort() method. So these are the options available to the delegate. These methods just return an opaque object to the recovery system, which passes it to the low-level function. Then the low-level function tries to recover according to which object it receives. So the delegate doesn't actually know how each option is implemented, it just knows these are available options to recover.

Also, the restart() method takes a new filename as parameter, so the delegate even knows what data is needed to provide to a particular recovery option in order to help the low-level function recover.

Of course, the current implementation is very skeletal, and there are still many open issues:

- How does the delegate know *which* low-level function throws a
  particular Condition? For example, what if main() calls some function
  that calls openDataFile() many times? What if openDataFile() is called
  at different points in the function call hierarchy? How does the
  delegate know which recovery choice is appropriate for every
  FileNotFoundCond() that it catches?

- Every Condition the program might encounter requires a lot of code:
  you need to define a Condition subclass, populate it with recovery
  strategies, and then have the throwing code check and handle each
  option. Is there a way to reduce the amount of code you need to write
  for every Condition?

- Also, Conditions seem to specific to a particular situation. It's not
  too bad for generic problems like FileNotFoundCond; we know what it
  means when the OS says "file not found", and we generally know what
  can be done to fix that. But what about ParseErrorCond? The delegate
  would need to know what kind of parse error, or even which parser
  issued that error, otherwise how would it know how to correct the
  parse error?

  But this means that every different parser in the program will require
  its own ParseError subclass, along with the associated recovery
  options. Seems like a lot of work for only occasional benefit.

- Are there general recovery options that apply generally across the
  majority of Conditions? If so, we can alleviate delegates from having
  to know the intimate details of a particular operation, which
  introduces too much coupling between high-level and low-level code.

A more minor issue is that the current implementation is not very well written. :) I'll have to think about this more, to know how to better implement it. But I wanted to get the semantics of it out first, so that at least we can start discussing the conceptual aspects of the idea.


T

-- 
They say that "guns don't kill people, people kill people." Well I think the gun helps. If you just stood there and yelled BANG, I don't think you'd kill too many people. -- Eddie Izzard, Dressed to Kill
February 20, 2012
On Mon, Feb 20, 2012 at 5:04 PM, Johannes Pfau <nospam@example.com> wrote:

> Am Mon, 20 Feb 2012 15:28:33 -0200
> schrieb Jose Armando Garcia <jsancio@gmail.com>:
>
> > I have been thinking of making a module for i18n model after gettext but taking advantage of D's language features. Is there some interest in this?
>
> Yep we need this. I also thought about developing an i18n module maybe
> we can work together on one. I won't have time for it the next 3
> weeks though.
> Anyway, I think we should base our i18n module on boost.locale
> http://www.boost.org/doc/libs/1_48_0/libs/locale/doc/html/index.html
> but boost.locale is pretty big, we should probably start with the
> translation part only:
> http://www.boost.org/doc/libs/1_48_0/libs/locale/doc/html/index.html
>
>
Sounds good! I'll probably wont start before that time either. Let me think about it some more and we can talk after the std.log review.


> The API is quite good imho. It'll need some changes to fit D better, but I think this could become a nice D style API.
>
> Boost.locale uses the gettext format internally which is important. This way we can use all the gettext tools & websites and the translator community (https://www.transifex.net/start/).
>
> BTW: I already have code to read the gettext format, so that could be used.
>

That is great! It would be great if we can make a state of the art I18N module. Looking forward to it!


> >
> > Thanks,
> > -Jose
> >
>
>


February 20, 2012
Le 20/02/2012 20:27, Jonathan M Davis a écrit :
> On Monday, February 20, 2012 11:15:08 H. S. Teoh wrote:
>> On Mon, Feb 20, 2012 at 01:52:15PM -0500, Jonathan M Davis wrote:
>> [...]
>>
>>> So, instead of
>>>
>>> catch(SpecificException1 e)
>>> {
>>>
>>> //use fields specific to this exception to do whatever you need to do
>>>
>>> }
>>> catch(SpecificException2 e)
>>> {
>>>
>>> //use fields specific to this exception to do whatever you need to do
>>>
>>> }
>>> catch(GenericException e)
>>> {
>>>
>>> //handle the generic exception as best you can given the lack of
>>> //a specific one
>>>
>>> }
>>>
>>> you end up with something effectively along the lines of
>>>
>>> catch(GenericException e)
>>> {
>>>
>>> if(/* e is SpecificException1 */)
>>> {
>>> //use fields specific to this exception to do whatever you need to do
>>> }
>>> else if(/* e is SpecificException2 */)
>>> {
>>> //use fields specific to this exception to do whatever you need to do
>>> }
>>> else
>>> {
>>> //handle the generic exception as best you can given the lack of
>>> //a specific one
>>> }
>>>
>>> }
>>
>> [...]
>>
>> I think what Andrei wants to do is more along these lines:
>>
>> catch(Exception e) {
>> writeln(formatLocaleString(e.fmt, e.data));
>> }
>>
>> I think there's some merit to this idea. However, I'm still unsure about
>> storing stuff in a Variant.
>
> Except that if you're not printing out the message, if all of the data is in
> e.data as a variant, then you _do_ end up with code like I gave. The variant
> is a bad idea for anything trying to actually handle the exception rather than
> just print out a message.
>

Have you considered this : http://forum.dlang.org/thread/jhos0l$102t$1@digitalmars.com?page=25#post-jhtus4:2416tp:241:40digitalmars.com

>> That's why I proposed to use runtime reflection to scan the exception
>> object for applicable fields. Then you get the best of both worlds: the
>> message formatter doesn't need to know what the fields are, and you get
>> full compile-time type checking for catching code that directly accesses
>> the fields.
>
> That would certainly be better.
>
> - Jonathan M Davis

This is way better than Variant[string], but unimplemented ATM.
February 20, 2012
On Mon, Feb 20, 2012 at 08:23:05PM +0100, deadalnix wrote: [...]
> Why not use tupleof on the Exception instead of Variant[string] ?

+1.

Compile-time type-checking and runtime generic access to fields.  Best of both worlds. Excellent idea!


T

-- 
Ruby is essentially Perl minus Wall.
February 20, 2012
On 2/20/12, Juan Manuel Cabo <juanmanuel.cabo@gmail.com> wrote:
> will be trouble. Instead please do:
>
>         "The '%1$s' file's size is %2$d which is wrong"
>

That is the shittiest formatting specifier ever invented. The unreadability of it is why I never, ever, use it. Python solved this nicely with its {0} {1} syntax:

>>> print '{0} and {1}'.format('foo', 'bar')
February 20, 2012
Le 20/02/2012 20:32, Juan Manuel Cabo a écrit :
> So, if your boss wants the URL of the request that was made
> when the standard library threw you a FileNotFoundException,
> you can do:
>
>
> 	try {
> 	      ...
>          } catch (Exception ex) {
>                  //Rethrow the exception with the added detail:
> 		ex.details["custom_url"] = getenv("URI");
>                  throw ex;
>          }
>
> (don't beat me if URI wasn't the envvar that apache sends for uri, I
> don't remember it at the moment).
>
> --jm
>
>
>
> On 02/20/2012 04:27 PM, Juan Manuel Cabo wrote:
>>> And so variant is the way to go ?
>>>
>>> Clearly, this is a very strong arguement in favor of typed Exception, that provide usefull information about what went
>>> wrong. This is a safe approach.
>>>
>>> Because this Variant stuff is going to require massive ducktyping of Exceptions, with all possible errors involved. The
>>> keys in the Variant[string] will depend on the Exception the dev is facing. This should be avoided and should warn us
>>> about the requirement of typed Exceptions.
>>
>>
>> Some of the things that characterize an exception, their traits, are
>> transversal to any hierachy that you can imagine, now and in the future.
>>
>> You can choose to keep changing a hierarchy, or build in some mechanism
>> to the Exception base class, that will allow you to get your traits
>> without downcasting.
>>
>> Say that at your place of work the boss decides that all exception classes
>> should have a COM error code, or that all exception classes should
>> provide the URL of the request that generated it.
>>
>> You know what will happen?
>>
>> Your boss will require you to derive all your exception classes from
>> COMException or from WebRequestException and then redefine FileNotFound
>> as a subclass of them. So you will have your FileNotFoundException
>> different than the standard library exception.
>>
>> Don't believe me? It happened to .NET... they've got a COMException
>> that wraps any other kind of error during a COM call.
>>
>>
>> --jm
>>
>
That wouldn't work, because you'll erase the stacktrace.

Plus, you are confusing inheritance with composition here. What you want is throw a COMException and link it to the original Exception. You have to consider Exception as a linkedlist, one being the cause of another.