title: Testing an impure function
body: <p>As part of an online programming course (<a href="https://www.edx.org/course/introduction-computer-science-mitx-6-00-1x-5" rel="nofollow noreferrer">6.00.1x</a>), I'm asked (<a href="https://courses.edx.org/courses/course-v1:MITx+6.00.1x_7+3T2015/courseware/19136f9d4de045fdab0ce099230f5385/af94467328b74ed38f0e901460166d70/" rel="nofollow noreferrer">Quiz p8</a>) to create a function, <code>satisfiesF(L)</code>, that filters <code>L</code> in-place using <code>f</code>, then returns the length of <code>L</code>.</p>
  
  <ul>
  <li><code>f</code> is a function defined for me that returns <code>True</code> for items that should remain in the list</li>
  <li>The remaining list items should be in the same order as before  </li>
  </ul>
  
  <p>I've written 2 solutions to this problem, tested them, and submitted them, but both were rejected. No reason was provided, as the problem is designed to test our ability to come up with our own test cases. For this reason, <strong>please do not provide working code</strong>, but rather give me a general idea of what's going wrong. I see 3 main possibilities at the moment:</p>
  
  <ul>
  <li>I have misunderstood the problem</li>
  <li>I made a subtle programming mistake</li>
  <li>edX made a mistake with their test cases <em>(unlikely)</em></li>
  </ul>
  
  <p>Here are my 2 solutions:</p>
  
  <pre><code>def satisfiesF(L):
      L[:] = [i for i in L if f(i)]
      return len(L)
  </code></pre>
  
  <p></p>
  
  <pre><code>def satisfiesF(L):
      i = 0
      while len(L) &gt; i:
          if f(L[i]): i += 1
          else: L.pop(i)
      return len(L)
  </code></pre>
  
  <p>Here is the full description of the problem verbatim:</p>
  
  <blockquote>
    <p>Write a Python function called <code>satisfiesF</code> that has the specification
    below. Then make the function call <code>run_satisfiesF(L, satisfiesF)</code>. Your
    code should look like:</p>
  
  <pre><code>def satisfiesF(L):
      """
      Assumes L is a list of strings
      Assume function f is already defined for you and it maps a string to a Boolean
      Mutates L such that it contains all of the strings, s, originally in L such
              that f(s) returns True, and no other elements. Remaining elements in L
              should be in the same order.
      Returns the length of L after mutation
      """
      # Your function implementation here
  
  run_satisfiesF(L, satisfiesF)
  </code></pre>
    
    <p>For your own testing of <code>satisfiesF</code>, for example, see the following test function <code>f</code> and test code:</p>
  
  <pre><code>def f(s):
      return 'a' in s
  
  L = ['a', 'b', 'a']
  print satisfiesF(L)
  print L
  </code></pre>
    
    <p>Should print:</p>
  
  <pre><code>2
  ['a', 'a']
  </code></pre>
    
    <p>Paste your entire function <code>satisfiesF</code>, including the definition, in the box below. After you define your function, make a function call to <code>run_satisfiesF(L, satisfiesF)</code>. Do not define <code>f</code> or <code>run_satisfiesF</code>. Do not leave any debugging print statements.</p>
    
    <p>For this question, you will not be able to see the test cases we run. This problem will test your ability to come up with your own test cases.</p>
  </blockquote>
  
  <p>And, for the sake of completeness, here are my latest set of tests (I'm using <a href="https://docs.python.org/2/library/doctest.html" rel="nofollow noreferrer"><code>doctest</code></a>):</p>
  
  <pre><code>&gt;&gt;&gt; L = ['bat', 'cat', 'dog', 'elephant']
  &gt;&gt;&gt; satisfiesF(L) == len([i for i in L if f(i)])
  True
  &gt;&gt;&gt; [i for i in L if not f(i)]
  []
  &gt;&gt;&gt; L = ['ab', 'b', 'ac']
  &gt;&gt;&gt; satisfiesF(L)
  2
  &gt;&gt;&gt; L
  ['ab', 'ac']
  &gt;&gt;&gt; L = ['a', 'a', 'b']
  &gt;&gt;&gt; satisfiesF(L)
  2
  &gt;&gt;&gt; L
  ['a', 'a']
  &gt;&gt;&gt; L = ['a', 'a', 'a']
  &gt;&gt;&gt; satisfiesF(L)
  3
  &gt;&gt;&gt; L
  ['a', 'a', 'a']
  &gt;&gt;&gt; L = ['b', 'c', 'd', 'a']
  &gt;&gt;&gt; satisfiesF(L)
  1
  &gt;&gt;&gt; L
  ['a']
  </code></pre>
  
  <p>These tests use <code>def f(s): return 'a' in s</code> as suggested in the problem. I haven't tested with other functions for <code>f</code>, but I don't think that would affect the outcome.</p>
  
  <p>I've tried replacing <code>satisfiesF(L)</code> with <code>run_satisfiesF(L, satisfiesF)</code>, but the tests still pass.</p>
  
  <hr/>
  
  <p><a href="https://stackoverflow.com/search?q=satisfiesF">Other questions about 6.00.1x Quiz p8</a></p>
  
  <hr/>
  
  <p>Proof that I'm not crazy:</p>
  
  <p><a href="https://i.stack.imgur.com/mvodz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mvodz.png" alt="answer to Quiz p8 marked incorrect"></a></p>