views:

49

answers:

1

I've got a list consisting of smaller lists inside of it, each list consisting of 2 items:

[[a,1],[b,2],[c,3]]  

I'm using a function called take(1,L,R) to take the first item from list L and return the item R. The code for the take function is here:

take(0,X,X).
take(N,[H|T],[H|R]):- 
    N>0, M is N-1,
    take(M,T,R).  

At the moment a run may look like this:

1 ?- take(1,[[a],[b],[c]],Taken).
Taken = [[a], [b], [c]]

Which is the same as the input! This is the same for a "regular" 1-level-depth list:

2 ?- take(1,[a,b,c],Taken).
Taken = [a, b, c]

Question:
The question for you is how can I make the result look like:

1 ?- take(1,[[a],[b],[c]],Taken).
Taken = [a]

I want to return the first N items of the list I send it.

A: 

Your base case take(0, X, X). is doing exactly what it says -- given any value X, the result is X. What I think you were trying to say is take(1, [H|T], H). (which yields the first element of a list).

What I think you're actually after is take(0, _, [ ]). which yields an empty list when "taking" 0 items from any list. This works well with your existing recursive case.

You say that you want to get the "first N items of the list" -- such a result must be stored in a list of N items. It follows that take(1, [a, b, c], Taken) would yield Taken = [a], not Taken = a. Similarly, take(1, [[a], [b], [c]], Taken). would yield Taken = [[a]].. To special-case the take(1, ...) form to return the first item only (without it being wrapped in a list) would break your recursion.

Cameron
the base case take(0, X, X). was meant to always return the input if N was 0, "you didnt want to remove anything, here you go" kind of thing. The whole function is supposed to work like "Take the N first items"
shaungus
@shaungus: OK, I understand now the thinking behind your original base case, but it doesn't work with your recursion, which says "the take(n) of a list is the head of that list with the take(n-1) of the tail of that list" -- when n-1 reaches 0, the take should be 0 items. You could alternatively define the base case as `take(1, [H|T], H).`, leaving take(0) undefined, if this makes more sense to you (you'd need to change the N>0 subgoal to N>1 in your recursive case). I personally prefer having take(0) return an empty list since that makes sense and seems valid to me ("give me 0 items")
Cameron
ok, well I might have had two different ways of thinking depending on where I was in the function, I can see it now X). Anyways I got it working, thanks
shaungus