Как оценить переменную со строковым значением? - PullRequest
1 голос
/ 07 апреля 2019

Мой код отлично работает с числами, но ошибка с одинарными кавычками. Я пытаюсь написать foldl функцию. Когда я делаю foldl1(concat, ['a','b'], X), он сообщает как "ERROR: Arithmetic: 'ab/0' is not a function". в чем проблема? Пролог не позволяет использовать is со строкой?

foldl1(P, [H], X) :-
    X is H.

foldl1(P, [H|T], X) :-
    foldl1(P, T, Y),
    call(P, H, Y, Z),
    X is Z.

Ответы [ 2 ]

2 голосов
/ 07 апреля 2019

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'.

Теперь переводчик «знает», что после первого ответа больше нет ответов ...

1 голос
/ 07 апреля 2019

Также возможно реализовать предикат foldl1/3 с использованием индексации по первому аргументу, чтобы избежать ложных точек выбора без разрезов, и это также хвостовая рекурсия.Из библиотеки Logtalk meta объект:

:- meta_predicate(foldl1(3, *, *)).
foldl1(Closure, [Head| Tail], Result) :-
    fold_left_(Tail, Closure, Head, Result).

fold_left_([], _, Result, Result).
fold_left_([Arg| Args], Closure, Acc, Result) :-
    call(Closure, Acc, Arg, Acc2),
    fold_left_(Args, Closure, Acc2, Result).

Примеры вызовов:

?- meta::foldl1(plus,[1,2,3],R).
R = 6.

?- meta::foldl1(concat,[1,2,3],R).
R = '123'.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...