I was trying to create a function that returns a list without any repetition using recursion, but I found something intriguing.
When I write the code like this:
def norep(xs):
if len(xs) == 0:
return xs
if xs[0] in norep(xs[1:]):
return xs[1:]
else:
return xs
l = norep([1, 2, 33, 4, 5, 2, 1, 24, 34, 2, 3, 5])
print(l)
the code returns this:
[2, 33, 4, 5, 2, 1, 24, 34, 2, 3, 5]
When I write it like this:
def norep(xs):
if len(xs) == 0:
return xs
if xs[0] in xs[1:]:
return norep(xs[1:])
else:
return [xs[0]] + norep(xs[1:])
l = norep([1, 2, 33, 4, 5, 2, 1, 24, 34, 2, 3, 5])
print(l)
it returns the expected output:
[33, 4, 1, 24, 34, 2, 3, 5]
Why doesn't the first code work, but the second one does?
This bit of code:
if xs[0] in xs[1:]:
return norep(xs[1:])
Does the following:
xs[0] in xs[1:]
xs[0]
(some value), evaluates xs[1:]
(some other value), and the resulting value of the evaluation is a boolean representing whether the first value is in the second value (however that's defined for those values).True
, runs the next line.norep(xs[1:])
and will return the outcome as the return value of the functionxs[1:]
, and passes the result to norep()
as the first argument.So, if xs[0] in xs[1:]
, the return value of the recursive call will be returned.
However, this bit of code:
if xs[0] in norep(xs[1:]):
return xs[1:]
Does the following:
xs[0] in norep(xs[1:])
xs[0]
(some value), then evaluates norep(xs[1:])
etc.norep(xs[1:])
means it evaluates xs[1:]
, and passes the result to norep()
as the first argumentxs[0]
is in the return value of that function call, runs the next linexs[1:]
.So, in both cases, the function is called recursively. But in the first example, the return value of the recursive call is returned. In the second example, the return value is always xs[1:]
.
In the else
part, xs
is returned, so no return value of the second example's function ever includes the return value of the recursive call.