Reputation: 2765
I wrote a predicate take(List,N,Result)
that returns in Result
the first N
elements of List
. I used two predicates to check if List
is actually a list and if List
has at least N
elements, and I want to output the corresponding errors. This is what I did, that works, but it seems not the best style to me, so I'm asking: how can I improve it? In particular the use of false
and the cut seems a too much complicated way to me, but I'm new to Prolog, so I really don't know and asking here.
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
).
Upvotes: 0
Views: 296
Reputation: 18726
Building on the widely available, tried and tested predicates append/3
and length/2
we define:
take(List,N,Prefix) :-
append(Prefix,_,List),
length(Prefix,N).
Sample queries:
?- 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].
Upvotes: 1