is / 2 оценивает арифметическое выражение справа, а объединяет результат с членом слева. Объединение также выполняется с аргументами head ', так что вы можете написать упрощенный foldl1 / 3, такой как
foldl1(_, [H], H).
foldl1(P, [H|T], Z) :-
foldl1(P, T, Y),
call(P, H, Y, Z).
тест:
?- foldl1(plus,[1,2,3],R).
R = 6 ;
false.
?- foldl1(concat,[1,2,3],R).
R = '123' ;
false.
Я бы поместил вырез после базы рекурсии, поскольку [H]
и [H|T]
, где T=[]
перекрываются, чтобы избежать любого последнего вызова - который в любом случае потерпит неудачу - при возможном возврате, например, повторном вызове, вызванном мной, вводом ;
после ожидаемого первого ответа, пока переводчик ждет моего выбора.
После разреза (надеюсь, вы легко сможете определить, где его разместить), мы получим:
?- foldl1(plus,[1,2,3],R).
R = 6.
?- foldl1(concat,[1,2,3],R).
R = '123'.
Теперь переводчик «знает», что после первого ответа больше нет ответов ...