я пытаюсь написать двоичный предикат, чтобы взять один список, вычислить мод 5 для каждого элемента, а затем поместить его в другой список. до сих пор я сделал это,
mod5(X,L):- R = [], modhelper(R,L), write(R).
modhelper(X,L):- memb(E,L), mod2(E,Z), addtolist(Z,X,X), modhelper(X,L).
%Get an element from the list L.
memb(E,[E|_]).
memb(E,[_|V]):- memb(E,V).
%If element is integer, return that integer mod 5 else return as is.
mod2(N,Z):- isInt(N) -> Z is N mod 5 ; Z = N.
%add this modified element to the output list.
addtolist(Y,[],[Y]).
addtolist(Y,[H|T],[H|N]):- addtolist(Y,T,N).
memb, mod2, addtolist работают как положено, но я делаю что-то не так в modhelper, чего не могу понять. Любая помощь приветствуется.
Ответ 1 · рейтинг 1 · Kaarel
В SWI-Прологе:
mod5(X, Y) :-
Y is X mod 5.
apply_mod5_to_list(L1, L2) :-
maplist(mod5, L1, L2).
Использование:
?- apply_mod5_to_list([2, 4, 6, 8], L2).
L2 = [2, 4, 1, 3].
?- apply_mod5_to_list([2, 4.1, 6, 8], L2).
ERROR: mod/2: Type error: `integer' expected, found `4.1'
?- apply_mod5_to_list([2, not_number, 6, 8], L2).
ERROR: is/2: Arithmetic: `not_number/0' is not a function
Вы можете легко изменить этот код, если хотите немного другого поведения, например. если вы хотите терпеть нецелые числа (кстати, зачем вам это?).
Если вы не можете использовать maplist, вы можете реализовать его самостоятельно, по крайней мере, в более специализированной версии, например. что-то вроде этого:
partition_the_list_into_first_and_rest([X | Xs], X, Xs).
% The result on an empty list is an empty list
apply_mod5_to_list([], []).
% If the input list contains at least one member
apply_mod5_to_list(L1, L2) :-
partition_the_list_into_first_and_rest(L1, X, Xs),
call(mod5, X, Y),
partition_the_list_into_first_and_rest(L2, Y, Ys),
apply_mod5_to_list(Xs, Ys).
К этому коду вы все еще можете применить много синтаксических упрощений, что вам, вероятно, следует сделать, чтобы превратить его в приемлемое решение для домашней работы...