-3

My goal is to sum a list without using mutation.

def noMutObj(lst,pointer=0, result=0):
    if pointer == len(lst): 
        return result
    newResult = result + lst[pointer]
    return noMutObj(lst, pointer+1, newResult) 

Would we consider pointer mutating as we take a step into the recursion, or does mutation apply only to a variable changing in a iterative loop?

Prune
  • 76,765
  • 14
  • 60
  • 81
Artemis
  • 139
  • 12
  • 2
    Do the values in `lst` change? No? Then there is no mutation. – Martijn Pieters Mar 09 '18 at 17:42
  • (...and to be clear, that doesn't mean "the values bound to the name `lst`", but rather, "the values within a single instance of `lst`"; you can bind a different list instance to the same name, but if you don't change the contents of a single instance, there's no mutation). – Charles Duffy Mar 09 '18 at 17:51

1 Answers1

2

You haven't mutated pointer: you've passed a different value into each call to noMutObj. Each stack frame has its own pointer, none of which are changed. Even then, you would be changing only your local copy.

You would have mutation if you did something such as

lst.append(newResult)
return noMutObj(lst, pointer+1, newResult)

Before the call. Instead, the proper way to send an altered list to the next call would be something such as

return noMutObj(lst[:].append(newResult), pointer+1, newResult)

... which creates a new list, appends newResult and passes that temporary object to the next level.

I know this is not at all what you intended your function to do; I'm merely illustrating the syntactic and semantic principles.

UPDATE

Ah ... now that we have a purpose ...

Mutation:

def noMutObj(lst):
    if len(lst) == 0: 
        return 0
    return lst.pop() + noMutObj(lst)

No mutation:

def noMutObj(lst):
    if len(lst) == 0: 
        return 0
    return lst[0] + noMutObj(lst[1:])
Prune
  • 76,765
  • 14
  • 60
  • 81