The following code demonstrates such functionality
also including a count which might be useful
during recover when deciding to continue or give up .
~~~~~~~~ %&ZHcx;. ~~~~~~~~
/*
?- demo .
question about recover(user:task,1,ball(oops)) .
continue [yn] ? y
question about recover(user:task,2,ball(oops)) .
continue [yn] ? |: y
question about recover(user:task,3,ball(oops)) .
continue [yn] ? |: n
gaveup(user:task,3,ball(oops)) .
true.
*/
:- meta_predicate try(:,:,:) .
/*
Try to perform the goal supplied by _try_ ;
if that _try_ goal does throw a ball ,
then call _recover_ with 1st argument the _try_ and 2nd argument the _count_ and 3rd argument the _ball_ .
If that _recover_ does evaluate ``true`` then call the _try_ goal again ;
otherwise if that _recover_ does evaluate false
then call _gaveup_ with 1st argument the _try_ and 2nd argument the _count_ and 3rd argument the _ball_ .
*/
try(_try_,_recover_,_gaveup_) :-
(
try(_try_,_recover_,_gaveup_,0)
) .
try(_try_,_recover_,_gaveup_,_count_) :-
(
_COUNT_ is _count_ + 1 ,
catch(_try_,_ball_,try(_try_,_recover_,_gaveup_,_COUNT_,_ball_))
) .
:- meta_predicate try(:,:,:,-) .
try(_try_,_recover_,_gaveup_,_count_,_ball_) :-
(
call(_recover_,_try_,_count_,_ball_) ->
try(_try_,_recover_,_gaveup_,_count_) ;
call(_gaveup_,_try_,_count_,_ball_)
) .
demo :-
(
try(task,recover,gaveup)
) .
task :-
(
throw(ball(oops))
) .
:- meta_predicate recover(:,-,-) .
recover(_try_,_ball_,_count_) :- repeat ,
(
format('~Nquestion about ~q .',[recover(_try_,_ball_,_count_)]) ,
format('~Ncontinue [yn] ? ',[]) ,
flush_output ,
get(_code_) ,
(
(_code_ = 0'y ; _code_ = 0'Y) -> ! , true ;
(_code_ = 0'n ; _code_ = 0'N) -> ! , false ;
false
)
) .
:- meta_predicate gaveup(:,-,-) .
gaveup(_try_,_ball_,_count_) :-
(
format('~N~q .',[gaveup(_try_,_ball_,_count_)])
) .