Re: capture error - the better way?

2009-12-18 Thread Philip Potter
2009/12/18 Peter Scott pe...@psdt.com:
 On Wed, 16 Dec 2009 10:09:38 +, Philip Potter wrote:
 Yes, it can't fold the constant. That's no excuse for changing the
 behaviour of the program. What it should do is what I wrote in my
 previous email -- replace it with code that raises a runtime exception
 when executed -- ie a die Illegal division by zero.

 This is Perl.  The distinction between the compilation and run time phases
 is almost totally academic.  (For instance, use strict throws some
 exceptions at compile time and others at run time.)  Since there's no
 compiled executable produced, the only difference in behavior is that your
 program dies sooner than it would have.  Of course, conceivably it would
 not have died at all if the constant folding occurred in conditionally
 unexecuted code.

 So think of this as compile-time validation made possible by the use of
 constants: if your program *were* to execute that code, it would die.
 Better to know about that in advance than 49 hours into a 50 hour duty
 cycle.

I don't disagree with most of what you said. Yes, runtime and compile
time are not as clear as in a language like C. Yes, it's best to know
as soon as possible that a program has a potential problem. But my
issue is that here, no such problem exists, and yet perl is still
complaining about it.

Recall that the example here was a runtime error causing an exception
to be thrown _from within an eval {} block_. If the program were to
execute that code, it would not die, as you claim. It would instead
throw an exception which would be caught by the eval {} block,
recover, and continue. But by moving the runtime error to compile
time, and outside of the systems that you've set up to deal with the
error, perl is saying I think this code is broken when in fact it
isn't. perl has changed the behaviour of the problem.

I wouldn't mind if perl just issued a warning. Having a constant
expression 1/0 in code is probably a Bad Thing which the programmer
should be warned of. But since it's still valid code with a
predictable outcome, it should do what it's told, not try to second
guess what you wanted in some sort of DWIMery.

Thankfully, the people who wrote perl 5.10 seem to agree with me.

Phil

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-17 Thread Peter Scott
On Wed, 16 Dec 2009 10:09:38 +, Philip Potter wrote:

 2009/12/16 Shlomi Fish shlo...@iglu.org.il:
 On Tuesday 15 Dec 2009 17:14:25 Philip Potter wrote:
 If evaluating a constant expression results in a runtime exception,
 that runtime exception must happen at runtime, and not at compile
 time. In general, it is the duty of an optimizer never to change
 program behaviour, only performance.


 But this is a case where the compiler evaluates a constant expression
 and it results in an exception. So it cannot store it as a folded
 constant on the side for the run-time place. As a result, it throws a
 compile-time error.
 
 Yes, it can't fold the constant. That's no excuse for changing the
 behaviour of the program. What it should do is what I wrote in my
 previous email -- replace it with code that raises a runtime exception
 when executed -- ie a die Illegal division by zero.

This is Perl.  The distinction between the compilation and run time phases 
is almost totally academic.  (For instance, use strict throws some 
exceptions at compile time and others at run time.)  Since there's no 
compiled executable produced, the only difference in behavior is that your 
program dies sooner than it would have.  Of course, conceivably it would 
not have died at all if the constant folding occurred in conditionally 
unexecuted code.  

So think of this as compile-time validation made possible by the use of 
constants: if your program *were* to execute that code, it would die.  
Better to know about that in advance than 49 hours into a 50 hour duty 
cycle.

Perl has never made a promise about compilation phase vs runtime phase 
separation of duties you appear to want.

-- 
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/
http://www.informit.com/store/product.aspx?isbn=0137001274

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-16 Thread Shlomi Fish
On Tuesday 15 Dec 2009 17:14:25 Philip Potter wrote:
 2009/12/15 Shlomi Fish shlo...@iglu.org.il:
  On Tuesday 15 Dec 2009 15:53:28 Philip Potter wrote:
  How can Illegal division by zero be a compile-time error? It seems
  clear to me that it's a run-time error, which the optimizer has
  (wrongly) decided to raise at compile-time.
 
  Well, the Perl compiler tends to collapse constants. So if it sees
  something like:
 
  
  ... ( CONSTANT_EXPR() / 0 ) ...
 
 
  it will try to find the value of CONSTANT_EXPR() / 0 so it can optimise
  it as a constant for the interpreter, and then get a fault there. It's a
  standard optimisation technique that also exists in other compilers such
  as gcc that are collapsing such constant expressions. So it does get
  evaluated at compile- time and as such should be avoided.
 
 I'm well aware of constant folding, and yes it is a standard
 technique. But your description of it is incorrect.

Why?

 
 If evaluating a constant expression results in a runtime exception,
 that runtime exception must happen at runtime, and not at compile
 time. In general, it is the duty of an optimizer never to change
 program behaviour, only performance.
 

But this is a case where the compiler evaluates a constant expression and it 
results in an exception. So it cannot store it as a folded constant on the 
side for the run-time place. As a result, it throws a compile-time error.

 Therefore an optimizer which tries to fold a constant expression at
 compile time only to find a divide by zero exception should write code
 which raises a divide by zero exception at runtime. Raising a divide
 by zero exception at compile time is not what the original program
 did, and so it's not what the optimizer should do either.

Why?

 
 If an optimizer *were* allowed to move runtime errors to compile time,
 it wouldn't just prevent use of 1/0. The following reasonable (if
 unrealistic) example would not be guaranteed to compile:
 
 # Check if a division will emit any sort of exception (divide by zero,
 overflow, underflow, NaN, whatever)
 sub check_division {
 my ($n, $d) = @_;
 eval { $n/$d};
 return Invalid division if $@;
 return Valid division;
 }
 
 # and elsewhere...
 
 check_division(1,0);
 
 Why? Because if a sufficiently clever optimizer saw that somewhere in
 your code you call check_division(1,0), it could decide to inline the
 function there. And once it's done that, it can propagate the
 constants 1 and 0 into the local versions of the variables $n and $d,
 producing the constant expression 1/0 within the eval block. Now it
 merrily decides to calculate this expression's value at compile time,
 only to emit a compile-time error. If this error had happened at
 runtime, the program would have caught it and functioned entirely
 correctly; but by moving the exception to compile time -- and out of
 the eval block which was supposed to catch any exceptions -- the
 program won't even compile.

Well, Perl's optimizer is not that smart. It does not inline such functions 
because it doesn't know how many places they will get called. So you're spared 
in this case.

 
 If I am supposed to defend against such an overzealous optimizer, how
 would I write code that uses any block eval to catch exceptions? A
 sufficiently advanced optimizer could always use some method like that
 described above to precalculate the results of the eval, triggering an
 exception at compile time instead of runtime. Therefore block eval
 could never be guaranteed to catch runtime exceptions!

Well, a program can always have user-input (from files, STDIN, @ARGV, etc.) 
which no compiler or optimiser can predict. Sometimes this input will trigger 
certain exceptions which cannot be folded.

Regards,

Shlomi Fish

-- 
-
Shlomi Fish   http://www.shlomifish.org/
Original Riddles - http://www.shlomifish.org/puzzles/

Bzr is slower than Subversion in combination with Sourceforge. 
( By: http://dazjorz.com/ )

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-16 Thread Philip Potter
2009/12/16 Shlomi Fish shlo...@iglu.org.il:
 On Tuesday 15 Dec 2009 17:14:25 Philip Potter wrote:
 If evaluating a constant expression results in a runtime exception,
 that runtime exception must happen at runtime, and not at compile
 time. In general, it is the duty of an optimizer never to change
 program behaviour, only performance.


 But this is a case where the compiler evaluates a constant expression and it
 results in an exception. So it cannot store it as a folded constant on the
 side for the run-time place. As a result, it throws a compile-time error.

Yes, it can't fold the constant. That's no excuse for changing the
behaviour of the program. What it should do is what I wrote in my
previous email -- replace it with code that raises a runtime exception
when executed -- ie a die Illegal division by zero.

 Therefore an optimizer which tries to fold a constant expression at
 compile time only to find a divide by zero exception should write code
 which raises a divide by zero exception at runtime. Raising a divide
 by zero exception at compile time is not what the original program
 did, and so it's not what the optimizer should do either.

 Why?

Uhm, because it changes the behaviour of the program? I don't see what
else I can say. If the optimizer changes program behaviour then you
have no guarantee that what you wrote is what will happen.

 If this error had happened at
 runtime, the program would have caught it and functioned entirely
 correctly; but by moving the exception to compile time -- and out of
 the eval block which was supposed to catch any exceptions -- the
 program won't even compile.

 Well, Perl's optimizer is not that smart. It does not inline such functions
 because it doesn't know how many places they will get called. So you're spared
 in this case.

I don't think you understand my point. The point is: even if it could,
it shouldn't. Once you allow optimizers to change program behaviour,
you have no guarantee that what you write is what will happen. That is
why optimizers must *never* change program behaviour.

 If I am supposed to defend against such an overzealous optimizer, how
 would I write code that uses any block eval to catch exceptions? A
 sufficiently advanced optimizer could always use some method like that
 described above to precalculate the results of the eval, triggering an
 exception at compile time instead of runtime. Therefore block eval
 could never be guaranteed to catch runtime exceptions!

 Well, a program can always have user-input (from files, STDIN, @ARGV, etc.)
 which no compiler or optimiser can predict. Sometimes this input will trigger
 certain exceptions which cannot be folded.

Sometimes the optimizer will be unable to break my code? That is no reassurance.

Phil

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-16 Thread Jenda Krynicky
From: Philip Potter philip.g.pot...@gmail.com
 2009/12/16 Shlomi Fish shlo...@iglu.org.il:
  On Tuesday 15 Dec 2009 17:14:25 Philip Potter wrote:
  If evaluating a constant expression results in a runtime exception,
  that runtime exception must happen at runtime, and not at compile
  time. In general, it is the duty of an optimizer never to change
  program behaviour, only performance.
 
 
  But this is a case where the compiler evaluates a constant expression and it
  results in an exception. So it cannot store it as a folded constant on the
  side for the run-time place. As a result, it throws a compile-time error.
 
 Yes, it can't fold the constant. That's no excuse for changing the
 behaviour of the program. What it should do is what I wrote in my
 previous email -- replace it with code that raises a runtime exception
 when executed -- ie a die Illegal division by zero.

An exception that get's raised every time is not very ... 
exceptional.

What it should do is what it did. Tell you you are doing something 
stupid.

Jenda
= je...@krynicky.cz === http://Jenda.Krynicky.cz =
When it comes to wine, women and song, wizards are allowed 
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery


-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Shlomi Fish
On Tuesday 15 Dec 2009 09:50:27 Xiao Lan (小兰) wrote:
 Hello,
 
 It seems in ruby and python we have a good exception capturing way.
 The ruby's:
 
 irb(main):042:0 begin
 irb(main):043:1*   x=12/0
 irb(main):044:1 rescue
 irb(main):045:1   puts 0 div error
 irb(main):046:1 end
 0 div error
 
 The python's:
  try:
 
 ...   x=12/0
 ... except:
 ...   print 0 div error
 ...
 0 div error
 
 
 
 But in Perl I have to use an eval:
 
 # perl -e '
 eval $x=12/0;
 if ($@) { print 0 div error }'
 0 div error
 
 
 
 So what's the equivalent of perl's exception handling like python/ruby?

You can use block eval {} instead of string eval :


#!/usr/bin/perl

use strict;
use warnings;

my $x;

eval
{
$x=12/0;
};

if ($@)
{ 
print 0 div error\n;
}


One problem with that is that Perl 5's exception handling is not inherently 
object-oriented. If you'd like that (and you likely would), look at the 
following CPAN modules:

* http://search.cpan.org/dist/Exception-Class/

* http://search.cpan.org/dist/TryCatch/ (never used it though).

* http://search.cpan.org/dist/Try-Tiny/ (likewise).

There's also http://search.cpan.org/dist/Error/ , which I've used, and have 
been co-maintaining, but cannot really recommend because it is Black Magick 
and quirky.

Regards,

Shlomi Fish

 
 Thanks in advance.
 

-- 
-
Shlomi Fish   http://www.shlomifish.org/
Stop Using MSIE - http://www.shlomifish.org/no-ie/

Bzr is slower than Subversion in combination with Sourceforge. 
( By: http://dazjorz.com/ )

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread 小兰
On Tue, Dec 15, 2009 at 6:34 PM, Shlomi Fish shlo...@iglu.org.il wrote:


 You can use block eval {} instead of string eval :

 
 #!/usr/bin/perl

 use strict;
 use warnings;

 my $x;

 eval
 {
    $x=12/0;
 };

 if ($@)
 {
    print 0 div error\n;
 }


I did have tried that, but this will get a runtime error.

# perl -e '
eval { $x = 12/0 };
if ($@) { print 0 div error }'

Illegal division by zero at -e line 2.


My perl version:

# perl -v

This is perl, v5.8.8 built for i486-linux-thread-multi




 One problem with that is that Perl 5's exception handling is not inherently
 object-oriented. If you'd like that (and you likely would), look at the
 following CPAN modules:

 * http://search.cpan.org/dist/Exception-Class/

 * http://search.cpan.org/dist/TryCatch/ (never used it though).

 * http://search.cpan.org/dist/Try-Tiny/ (likewise).


Thanks Shlomi, I will check out them.

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Philip Potter
2009/12/15 Xiao Lan (小兰) practicalp...@gmail.com:
 On Tue, Dec 15, 2009 at 6:34 PM, Shlomi Fish shlo...@iglu.org.il wrote:
 You can use block eval {} instead of string eval :
 I did have tried that, but this will get a runtime error.

 # perl -e '
 eval { $x = 12/0 };
 if ($@) { print 0 div error }'

 Illegal division by zero at -e line 2.

[OT: Are you running this as root? You should avoid being root
whenever you can.]

That's odd. It works on my machine:

$ perl -le '
eval { $x = 12/0 };
if ($@) { print 0 div error }'
0 div error
$ perl -v

This is perl, v5.10.0 built for x86_64-linux-gnu-thread-multi

I can only guess that perl5.8.8 is not catching exceptions in
constants caused by evaluating compile time constants. String eval
delays evaluation to runtime which would stop this bug manifesting;
but this feature is exactly the reason why string eval is /bad/. Does
this work for you?

$ perl -le 'eval {
  die died;
};
if ($@) { print Caught exception; }'

I would expect this to print Caught exception and not died, which
indeed is what happens on my machine.

Phil

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread 小兰
On Tue, Dec 15, 2009 at 7:50 PM, Xiao Lan (小兰) practicalp...@gmail.com wrote:



 I did have tried that, but this will get a runtime error.


Sorry this is exactly a compile-time error.

# cat except.pl

eval { $x=12/0 };
print 0 div error if $@;

# perl -c except.pl
Illegal division by zero at except.pl line 2.

So, can't we capture it at runtime when meeting such error?

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Shlomi Fish
On Tuesday 15 Dec 2009 14:25:28 Xiao Lan (小兰) wrote:
 On Tue, Dec 15, 2009 at 7:50 PM, Xiao Lan (小兰) practicalp...@gmail.com 
wrote:
  I did have tried that, but this will get a runtime error.
 
 Sorry this is exactly a compile-time error.
 
 # cat except.pl
 
 eval { $x=12/0 };
 print 0 div error if $@;
 
 # perl -c except.pl
 Illegal division by zero at except.pl line 2.
 
 So, can't we capture it at runtime when meeting such error?
 

No, you cannot capture compile-time errors at runtime. You'll need to make 
sure your code compiles before you run it. Note that you can capture such 
errors if you do perldoc -f require, perldoc -f do (for a filename), string 
eval , etc. at run-time, in which case perl 5 invokes its compiler to 
compile some code at run-time.

But for run-time exceptions block eval { ... } should work just as well.

Regards,

Shlomi Fish

-- 
-
Shlomi Fish   http://www.shlomifish.org/
Star Trek: We, the Living Dead - http://shlom.in/st-wtld

Bzr is slower than Subversion in combination with Sourceforge. 
( By: http://dazjorz.com/ )

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Philip Potter
2009/12/15 Shlomi Fish shlo...@iglu.org.il:
 On Tuesday 15 Dec 2009 14:25:28 Xiao Lan (小兰) wrote:
 On Tue, Dec 15, 2009 at 7:50 PM, Xiao Lan (小兰) practicalp...@gmail.com
 wrote:
  I did have tried that, but this will get a runtime error.

 Sorry this is exactly a compile-time error.

 # cat except.pl

 eval { $x=12/0 };
 print 0 div error if $@;

 # perl -c except.pl
 Illegal division by zero at except.pl line 2.

 So, can't we capture it at runtime when meeting such error?


 No, you cannot capture compile-time errors at runtime. You'll need to make
 sure your code compiles before you run it. Note that you can capture such
 errors if you do perldoc -f require, perldoc -f do (for a filename), string
 eval , etc. at run-time, in which case perl 5 invokes its compiler to
 compile some code at run-time.

How can Illegal division by zero be a compile-time error? It seems
clear to me that it's a run-time error, which the optimizer has
(wrongly) decided to raise at compile-time.

Phil

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Shlomi Fish
On Tuesday 15 Dec 2009 15:53:28 Philip Potter wrote:
 2009/12/15 Shlomi Fish shlo...@iglu.org.il:
  On Tuesday 15 Dec 2009 14:25:28 Xiao Lan (小兰) wrote:
  On Tue, Dec 15, 2009 at 7:50 PM, Xiao Lan (小兰) practicalp...@gmail.com
 
  wrote:
   I did have tried that, but this will get a runtime error.
 
  Sorry this is exactly a compile-time error.
 
  # cat except.pl
 
  eval { $x=12/0 };
  print 0 div error if $@;
 
  # perl -c except.pl
  Illegal division by zero at except.pl line 2.
 
  So, can't we capture it at runtime when meeting such error?
 
  No, you cannot capture compile-time errors at runtime. You'll need to
  make sure your code compiles before you run it. Note that you can capture
  such errors if you do perldoc -f require, perldoc -f do (for a filename),
  string eval , etc. at run-time, in which case perl 5 invokes its
  compiler to compile some code at run-time.
 
 How can Illegal division by zero be a compile-time error? It seems
 clear to me that it's a run-time error, which the optimizer has
 (wrongly) decided to raise at compile-time.
 

Well, the Perl compiler tends to collapse constants. So if it sees something 
like:


... ( CONSTANT_EXPR() / 0 ) ...


it will try to find the value of CONSTANT_EXPR() / 0 so it can optimise it 
as a constant for the interpreter, and then get a fault there. It's a standard 
optimisation technique that also exists in other compilers such as gcc that 
are collapsing such constant expressions. So it does get evaluated at compile-
time and as such should be avoided.

Regards,

Shlomi Fish

 Phil
 

-- 
-
Shlomi Fish   http://www.shlomifish.org/
The Case for File Swapping - http://shlom.in/file-swap

Bzr is slower than Subversion in combination with Sourceforge. 
( By: http://dazjorz.com/ )

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Philip Potter
2009/12/15 Shlomi Fish shlo...@iglu.org.il:
 On Tuesday 15 Dec 2009 15:53:28 Philip Potter wrote:
 How can Illegal division by zero be a compile-time error? It seems
 clear to me that it's a run-time error, which the optimizer has
 (wrongly) decided to raise at compile-time.


 Well, the Perl compiler tends to collapse constants. So if it sees something
 like:

 
 ... ( CONSTANT_EXPR() / 0 ) ...


 it will try to find the value of CONSTANT_EXPR() / 0 so it can optimise it
 as a constant for the interpreter, and then get a fault there. It's a standard
 optimisation technique that also exists in other compilers such as gcc that
 are collapsing such constant expressions. So it does get evaluated at compile-
 time and as such should be avoided.

I'm well aware of constant folding, and yes it is a standard
technique. But your description of it is incorrect.

If evaluating a constant expression results in a runtime exception,
that runtime exception must happen at runtime, and not at compile
time. In general, it is the duty of an optimizer never to change
program behaviour, only performance.

Therefore an optimizer which tries to fold a constant expression at
compile time only to find a divide by zero exception should write code
which raises a divide by zero exception at runtime. Raising a divide
by zero exception at compile time is not what the original program
did, and so it's not what the optimizer should do either.

If an optimizer *were* allowed to move runtime errors to compile time,
it wouldn't just prevent use of 1/0. The following reasonable (if
unrealistic) example would not be guaranteed to compile:

# Check if a division will emit any sort of exception (divide by zero,
overflow, underflow, NaN, whatever)
sub check_division {
my ($n, $d) = @_;
eval { $n/$d};
return Invalid division if $@;
return Valid division;
}

# and elsewhere...

check_division(1,0);

Why? Because if a sufficiently clever optimizer saw that somewhere in
your code you call check_division(1,0), it could decide to inline the
function there. And once it's done that, it can propagate the
constants 1 and 0 into the local versions of the variables $n and $d,
producing the constant expression 1/0 within the eval block. Now it
merrily decides to calculate this expression's value at compile time,
only to emit a compile-time error. If this error had happened at
runtime, the program would have caught it and functioned entirely
correctly; but by moving the exception to compile time -- and out of
the eval block which was supposed to catch any exceptions -- the
program won't even compile.

If I am supposed to defend against such an overzealous optimizer, how
would I write code that uses any block eval to catch exceptions? A
sufficiently advanced optimizer could always use some method like that
described above to precalculate the results of the eval, triggering an
exception at compile time instead of runtime. Therefore block eval
could never be guaranteed to catch runtime exceptions!

Philip

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: capture error - the better way?

2009-12-15 Thread Dr.Ruud

Xiao Lan (小兰) wrote:



eval $x=12/0;
if ($@) { print 0 div error }'
0 div error


Don't rely on testing $@, simply because it is
a global variable that can get changed everywhere.

Instead, test the return value of the eval itself.
(Don't forget to let it return 1 for success,
just like with modules.)

Avoid string-eval whenever possible.

  perl -wle '

my $y = 0;

if ( !eval { 42 / $y; 1 } ) {

my $error = $@ || unknown;

print $error;

}
  '
  Illegal division by zero at -e line 3.

--
Ruud

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/