Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's my solution:</p> <pre><code>(define (flatten-iter a-list) (define (flat-do acc lst-interm lst) (cond ((null? lst) (reverse acc)) ((and (list? lst-interm) (not (null? lst-interm))) (flat-do acc (car lst-interm) (append (cdr lst-interm) lst))) ((not (list? lst-interm)) (flat-do (cons lst-interm acc) empty lst)) ((list? (car lst)) (flat-do acc (car lst) (cdr lst))) (else (flat-do (cons (car lst) acc) empty (cdr lst))))) (flat-do empty empty a-list)) (flatten-iter (list 1 (list 2 (list 3 4 (list 5 empty 6))) 7 8)) =&gt; (1 2 3 4 5 6 7 8) </code></pre> <p>Tail-recrusive functions require that they never return, and thus you can't use stack for storing your program's state. Instead, you use function arguments to pass the state between function calls. Therefore, we need to determine how to maintain the state. Because the result of our function is <code>list?</code>, it's meaningful to grow an <code>empty</code> list; we're using <code>acc</code> for this purpose. You can see how it works in <code>else</code> branch above. But we should be able to process nested lists. And while we're going deeper, we should keep the rest elements of the nested list for further processing. Sample list: <code>(list 1 (list 2 3) 4 5)</code></p> <p>Until <code>(list 2 3)</code> we have already added <code>1</code> to accumulator. Since we can't use stack, we need some other place to store the rest elements of the list. And this place is the <code>lst</code> argument, which contains elements of the original list to be flattened. We can just <code>append</code> the <code>lst</code> to the rest elements <code>(cdr (list 2 3))</code> which are <code>(list 3)</code>, and proceed with the list's head we stumbled upon while flattening, i. e. (car (list 2 3)) which is just <code>2</code>. Now, <code>(and (list? lst-interm) (not (null? lst-interm)))</code> succeeds because <code>flat-do</code> is called this way:</p> <pre><code>(flat-do (list 1) (list 2 3) (list 4 5)) </code></pre> <p>and the condition triggers this code:</p> <pre><code>(flat-do (list 1) (car (list 2 3)) (append (cdr (list 2 3)) (list 4 5))) </code></pre> <p><code>flat-do</code> again is called this way: (flat-do (list 1) 2 (list 3 4 5))</p> <p>The condition <code>(not (list? 2))</code> now succeeds and the code <code>(flat-do (cons 2 1) empty (list 3 4 5))</code> is evaluated.</p> <p>The rest processing is done with <code>else</code> branch until <code>lst</code> is <code>null?</code> and <code>reverse</code> is performed on <code>acc</code>. Function then returns the reversed accumulator.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload