<div class="notebook"> <div class="nb-cell markdown" name="md1"> # Breaking between/3 based “loop” in SWI-Prolog while maintaining choice points that follow it See https://stackoverflow.com/questions/53388456/breaking-between-3-based-loop-in-swi-prolog-while-maintaining-choice-points-th </div> <div class="nb-cell program" data-background="true" name="p2"> do_something(Input, N, Output) :- N >= 5, ( maplist(plus(1), Input, Output) ; maplist(plus(2), Input, Output) ). </div> <div class="nb-cell markdown" name="md2"> The trick is to use *->/2, which takes the _if_ branch if there is at least one solution and the _then_ if there is none. So, we start like below. </div> <div class="nb-cell program" name="p1"> main(InputList, N, OutputList) :- length(InputList, Length), between(1, Length, N), ( do_something(InputList, N, OutputList) *-> true ; fail ). </div> <div class="nb-cell query" data-tabled="true" name="q1"> numlist(1, 10, Input), main(Input, N, Output). </div> <div class="nb-cell markdown" name="md3"> We cannot cut (!) a the place of the `true` as this will also kill the choice point of the do_something/3. Therefore we must use non-backtrackable state. The thing below is rather hacky. </div> <div class="nb-cell program" name="p3"> main(InputList, N, OutputList) :- length(InputList, Length), State = state(cont), between(1, Length, N), ( State = state(cont) -> true ; !, fail ), ( do_something(InputList, N, OutputList) *-> nb_setarg(1, State, stop) ; fail ). </div> <div class="nb-cell query" data-tabled="true" name="q2"> numlist(1, 10, Input), main(Input, N, Output). </div> </div>