Skip Menu |

This queue is for tickets about the future CPAN distribution.

Report information
The Basics
Id: 84188
Status: resolved
Priority: 0/
Queue: future

People
Owner: Nobody in particular
Requestors: TOSHIOITO [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.11
Fixed in: 0.12



Subject: Error message is not user-friendly for followed_by(), and_then(), or_else() and repeat()
I often forget to return a Future in the callback for followed_by(), and_then() or or_else() method, especially when I just mean to provide other parts of my program with a way to chain further callbacks. In this case, the error message should be more user-friendly. Example: use Future 0.11; my $f = Future->new; $f->and_then(sub { do_something(shift->get); ## this does not return anything }); $f->done("result"); Current error message: Can't call method "on_ready" on an undefined value at /usr/local/share/perl/5.14.2/Future.pm line 223. Should be like: You must return a Future from and_then callback at your_script.pl line XXX. The same applies to Future::Utils::repeat function. Example: my $ef = Future::Utils::repeat { do_something(); } while => sub { 0 }; Current error message: Can't call method "new" on an undefined value at /usr/local/share/perl/5.14.2/Future/Utils.pm line 181.
On Mon Mar 25 01:10:30 2013, TOSHIOITO wrote: Show quoted text
> I often forget to return a Future in the callback for followed_by(), > and_then() or or_else() method, especially when I just mean to provide > other parts of my program with a way to chain further callbacks. > > In this case, the error message should be more user-friendly.
... Show quoted text
> You must return a Future from and_then callback at your_script.pl > line XXX.
Ahyes. That can be neatened up. I imagine that because it's a "static" typing error in the code itself, not some sort of runtime failure of the operation, it should indeed be an immediate croak. -- Paul Evans
The attached patch fixes this. $ perl -Mblib -MFuture -E 'my $f = Future->new->done->and_then(sub{})' Expected code to return a Future in and_then at -e line 1 -- Paul Evans
Subject: rt84188.patch
=== modified file 'lib/Future.pm' --- lib/Future.pm 2013-03-26 18:49:17 +0000 +++ lib/Future.pm 2013-03-26 21:46:49 +0000 @@ -199,6 +199,11 @@ my $f1 = shift; my ( $code ) = @_; + # For later, we might want to know where we were called from + my $func = "followed_by"; + $func = (caller 1)[3] and $func =~ s/^.*::// if caller eq __PACKAGE__; + my $where = Carp::shortmess "in $func"; + my $fseq = $f1->new; my $f2; @@ -213,6 +218,10 @@ return; } + unless( blessed $f2 and $f2->isa( "Future" ) ) { + die "Expected code to return a Future $where"; + } + $f2->on_ready( sub { my $f2 = shift; if( $f2->is_cancelled ) { @@ -232,9 +241,6 @@ } ) if not $fseq->is_ready; if( !defined wantarray ) { - my $func = "followed_by"; - $func = (caller 1)[3] and $func =~ s/^.*::// if caller eq __PACKAGE__; - Carp::carp "Calling ->$func in void context"; } === modified file 't/02followed_by.t' --- t/02followed_by.t 2013-03-22 19:59:35 +0000 +++ t/02followed_by.t 2013-03-26 21:46:49 +0000 @@ -124,7 +124,21 @@ Future->new->done->followed_by( sub { Future->new } ); - } "Calling ->followed_by in void context"; + } "Calling ->followed_by in void context", + 'Warning in void context'; +} + +# Non-Future return raises exception +{ + my $f1 = Future->new; + + my $file = __FILE__; + my $line = __LINE__+1; + my $fseq = $f1->followed_by( sub {} ); + + like( exception { $f1->done }, + qr/^Expected code to return a Future in followed_by at \Q$file\E line $line\.?/, + 'Exception from non-Future return' ); } done_testing; === modified file 't/03and_then.t' --- t/03and_then.t 2013-03-22 20:10:09 +0000 +++ t/03and_then.t 2013-03-26 21:46:49 +0000 @@ -160,7 +160,21 @@ Future->new->done->and_then( sub { Future->new } ); - } "Calling ->and_then in void context"; + } "Calling ->and_then in void context", + 'Warning in void context'; +} + +# Non-Future return raises exception +{ + my $f1 = Future->new; + + my $file = __FILE__; + my $line = __LINE__+1; + my $fseq = $f1->and_then( sub {} ); + + like( exception { $f1->done }, + qr/^Expected code to return a Future in and_then at \Q$file\E line $line\.?/, + 'Exception from non-Future return' ); } done_testing; === modified file 't/04or_else.t' --- t/04or_else.t 2013-03-22 20:10:09 +0000 +++ t/04or_else.t 2013-03-26 21:46:49 +0000 @@ -165,7 +165,21 @@ Future->new->done->or_else( sub { Future->new } ); - } "Calling ->or_else in void context"; + } "Calling ->or_else in void context", + 'Warning in void context'; +} + +# Non-Future return raises exception +{ + my $f1 = Future->new; + + my $file = __FILE__; + my $line = __LINE__+1; + my $fseq = $f1->or_else( sub {} ); + + like( exception { $f1->fail(1) }, + qr/^Expected code to return a Future in or_else at \Q$file\E line $line\.?/, + 'Exception from non-Future return' ); } done_testing;
Thank you for fixing!