Subject: Re: please, answer on my FAQ (fwd)

From: "Richard A. O'Keefe" <[email-masked]>
Date: Tue, 28 Nov 2000 10:45:43 +1300 (NZDT)

What is the *point* of the n_times/2 predicate?

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% times counters
	%--------------------------------------------------------------------------
	% count +Goal success in ?Times or try +Goal +Times
	n_times(Goal, Times) :-
		gensym(n_times,Name),
		flag(Name, _N, 0),!,
		repeat,
		( Goal,
			flag(Name, N, N+1),
			fail
		; flag(Name, Times, _N)
		).

I can't figure out what it is supposed to do, and using "_N" twice doesn't
help (you are supposed to put "_" in front of variables that you only mean
to mention once).

If you want to execute a command N times, ignoring whether it succeeds
or fails, just do

    do_exactly_n_times(N, Goal) :-
	( between(1, N, _), call(Goal), fail ; true ).

If you want to repeatedly execute a command until it fails, and return
the number of times it succeeded, do

    count_successes(Goal, S) :-
	count_successes(Goal, 0, S).

    count_successes(G, S0, S) :-
        (   \+(G) -> S = S0
	;   S1 is S0 + 1,            
	    count_successes(G, S1, S)
	).

If you want to execute a command exactly N times, and return the
number of times it succeeded, do

    do_n_times_counting_successes(N, Goal, S) :-
	N >= 0,
        do_n_times_counting_successes(N, Goal, S0, S).

    do_n_times_counting_successes(N0, Goal, S0, S) :-
        (   N =:= 0 -> S = S0
        ;   \+(G) ->
	    N1 is N0 - 1,
	    do_n_times_counting_successes(N1, Goal, S0, S)
	;/* G succeeded */
	    N1 is N0 - 1,
	    S1 is S0 + 1,
	    do_n_times_counting_successes(N1, Goal, S1, S)
	).

Why program with clumsy side effects when you can say what you mean
faster and better without them?

If the documentation of flag/3 has the effect of discouraging people
from using it, then WONDERFUL, say I.  Perhaps people will learn how
to write Prolog instead.