name = 'del/3' slug = 'delete element from list' description = '''\
del(X, L1, L2)
: the list L2
is obtained from L1
by deleting element X
.
?- del(1, [1,2,3], L). L = [2,3]. ?- del(2, [1,2,3,2,5], L). L = [1,3,2,5] ; L = [1,2,3,5]. ?- del(X, [1,2,3], L). X = 1, L = [2,3] ; X = 2, L = [1,3] ; X = 3, L = [1,2].''' plan = ['''
This exercise is very similar to the exercise memb/2
, except that this time we also delete
the element we are looking for. Where in the list can element X
be hiding?
Remember that a list has two parts: head and tail. Therefore there are two possibilies!
What is the simplest option? Perhaps deleting the first element?
''', '''\How do I delete from the list's tail? Just divide the list into its head and tail, recursively (as the problem is one element smaller now) delete from the tail, and at the end don't forget about the head previously taken away.
''', '''\Recursive step: if we assume NewTail
is the tail with element X
already deleted,
then [H|NewTail]
is the whole list with element X
deleted.
The operator ==
is "stricter" than operator =
in the sense that
for the latter it is enough to be able to make the two operands equal (unification). Perhaps by using =
you can make the predicate del/3
more general (e.g. able to work with output arguments becoming inputs).
Of course, you can also solve the exercise without explicit use of either of these two operators, just remember that unification is implicitly performed with the predicate's arguments (head of clause).
''', 'eq_instead_of_equ_markup': '''\Perhaps the operator for unification (=) would be better?
''', 'base_case': '''\Did you think of a base case? Where in the list is it the easiest to delete an element?
''', 'recursive_case': '''\The base case is ok. However, what about the general recursive case?
''', 'predicate_always_false': '''\It seems your predicate is
If the name is correct, check whether something else is misspelled, perhaps there is a full stop instead of a comma or vice versa, or maybe you typed a variable name in lowercase?
It is, of course, also possible that your conditions are too restrictive, or even impossible to satisfy
(as would be, for example, the condition that an empty list []
is equal to a list with
exactly three elements [A,B,C]
,
or something similarly impossible).
Is there an infinite recursion at work here? How will it ever stop?
Or perhaps is there a missing, faulty, or simply incompatible (with the general recursive case) base case?
''', 'del_from_empty_list_success': '''\You can't delete an element from an empty list!
If I delete an element from an empty list, this doesn't result in an empty list or anything else, but it simply shouldn't succeed. You don't even have to include a rule for this as prolog by default acts like that. You know how prolog loves to say "no"! :)
If that is your base case, rethink it! Where in the list is it the easiest to delete an element?
''', 'lost_heads': '''\The element has been successfully deleted, but all the others before it got deleted too, right? Did you forget to put the head back at the front of the list after returning from recursion?
Try asking the following query:
?- del(d, [a,b,c,d,e,f,g], L).
Did you forget (copy/paste?) and used [X|T]
instead of the more general [H|T]
in the recursive case?
Of the following two queries one works and the other doesn't.
?- del(d, [d,d,d,d,e,f,g], L).
?- del(d, [a,b,c,d,e,f,g], L).
Interesting tidbit. Inserting and deleting an element into/from the list are opposite operations.
Just by playing around with the arguments you can solve del/3
using insert/3
.
Logically the following holds: deleting element X
from list BigList
resulting
in list SmallList
is the same as inserting element X
into list SmallList
to get list BigList
as a result. ;)