2015-09-14 6 views
0

Я написал предикат take(List,N,Result), который возвращает в Result первые N элементы List. Я использовал два предиката, чтобы проверить, действительно ли List список, и если List имеет не менее N элементов, и я хочу вывести соответствующие ошибки. Это то, что я сделал, это работает, но мне кажется, что это не лучший стиль, поэтому я спрашиваю: как я могу его улучшить? В частности, использование false и сокращение кажется мне слишком сложным для меня способом, но я новичок в Prolog, поэтому я действительно не знаю и спрашиваю здесь.Пролог улучшает код, чтобы проверить ввод пользователя

take(L,N,Result) :- 
    checkN(N), 
    check(L,N), 
    takeaux(L,N,Result). 

checkN(N) :- 
    ( N > 0 
    ; write('Error N must be positive'), 
     false 
    ), 
    !. 

check(L,N) :- 
    ( length(L,N1), 
     N1 >= N 
    ; write('Error: list has less than '), 
     write(N), 
     write(' elements'), 
     false 
    ). 

ответ

1

Основываясь на широко доступны, испытанный предикаты append/3 и length/2 мы определяем:

take(List,N,Prefix) :- 
    append(Prefix,_,List), 
    length(Prefix,N). 

Примеры запросов:

?- take([a,b,c,d,e,f,g],3,Prefix). 
    Prefix = [a,b,c]     % succeeds, b 
; false.        % terminates universally 

?- take([a,b,c,d,e,f,g],N,Prefix). 
    N = 0, Prefix = [] 
; N = 1, Prefix = [a] 
; N = 2, Prefix = [a,b] 
; N = 3, Prefix = [a,b,c] 
; N = 4, Prefix = [a,b,c,d] 
; N = 5, Prefix = [a,b,c,d,e] 
; N = 6, Prefix = [a,b,c,d,e,f] 
; N = 7, Prefix = [a,b,c,d,e,f,g] 
; false. 

?- take(List,3,[a,b,c]). 
List = [a,b,c|_A]. 

?- take(List,N,[a,b,c]). 
N = 3, List = [a,b,c|_A]. 
+0

Я знаю, что это может быть сделано таким образом, но мой вопрос касается предикатов 'check' и' checkN', забудьте на мгновение реализацию (что я сделал с предикатом 'takeaux' по-другому и работает). – rok

+0

@rok. Использование побочных эффектов для обработки ошибок затруднительно. В то время как 'checkN/1' работает, необходимо проверить' check/2': при выполнении запроса '? - check ([a, b, c], 2).' Я получаю 'true '; Ошибка: список имеет менее 2 элементов false.' ... – repeat

+0

он может легко фиксировать добавление разреза таким же образом, как я сделал в 'checkN', предотвращая возврат, но это мой реальный вопрос? Каким другим способом я могу выводить сообщения об ошибках? Мое решение кажется мне сложным, но я не могу найти никакого другого решения ... любой намек будет оценен! – rok