Recursion - Slicing the tail of list is impure
Posted on January 1, 2020
Tags: functional
One of the most common recursive methods is to slice the list tail
def fun(arr,x):
= arr[0]
head = arr[1:]
tail if Prop(head,x):
return DoSomething(head)
else:
= fun(tail,x)
IH return IH
It works most of the time…until it doesn’t.
Problem Statement: Find the index of element “x” in a list “arr” (using recursion)
The naive solution is :
- IH: Finds the element x in the tail arr and return it’s index
- Solve: Check if x in head arr return index 0, else IH.
Why doesn’t this work?
def func(arr,x):
= arr[0]
HeadValue = arr[1:]
tail = 0
HeadIndex
if HeadValue == x:
return HeadIndex
else:
#this will always return 0
= func(tail,x)
IH return IH
tail = arr[1:]
is impure.
It shifts the index of arr[1:]
by -1
.
Remediate the Side-Effect: IH = 1 + func(tail,x)
Error is due to assumption that lists are pure data structs and the INDEX-VALUE relation is immutable.
What we really wanted was a dictionary.
The below code does work when we convert list to dict.
The partition between head and tail of the dict maintains the INDEX-VALUE pairing.
= [5,8,2,5,24]
arr = lambda xs: dict(enumerate(xs))
ConvertListToDict #ConvertListToDict([5,8,3]) will return {0:5, 1:8, 2:3}
def findElemByIndex(arrX,x):
= ConvertListToDict(arrX.copy())
arr = list(arr.keys())
Indices = Indices.pop()
HeadIndex = arr.pop(HeadIndex)
HeadValue = arr
tail ###
if HeadValue==x:
return HeadIndex
else:
= findElemByIndex(tail,x)
IH return IH