How to manually flatten a list in Racket (Scheme)

11,662

The first implementation shown is self-contained but incorrect, and it's not calling Racket's built-in flatten - it's simply calling itself recursively, rename it to see what I mean. Here's a fixed version:

(define (my-flatten lst)
  (cond ((null? lst) empty) ; you wrote `list` instead of `lst`
        ((pair? (car lst))  ; it's more efficient if we use `pair?`
         (append (my-flatten (car lst)) (my-flatten (cdr lst))))
        (else (cons (car lst) (my-flatten (cdr lst))))))

Or a bit simpler:

(define (my-flatten lst)
  (cond ((null? lst) '())
        ((pair? lst)
         (append (my-flatten (car lst)) (my-flatten (cdr lst))))
        (else (list lst))))
Share:
11,662
James Combs
Author by

James Combs

Updated on June 04, 2022

Comments

  • James Combs
    James Combs almost 2 years

    How could one go about flattening a list without using the flatten function built in to racket?

    I understand that the default implementation of flatten is

    (define (flatten lst)
      (cond 
        ((null? list)
          empty)
        ((list? (car lst))
          (append (flatten (car lst)) (flatten (cdr lst))))
        (else
          (cons (car lst) (flatten (cdr lst))))))
    

    but im not entirely sure how to go about not using the flatten function as I do not know how it is working behind the scenes. I couldn't find a good explanation of this besides implementations of this code. Could someone please explain

    This is my very bad attempt and im pretty much clueless because this is not even close and will not run....

    (define acc null)
    (define (my-flatten lst)
      (cond
        [(null? lst) null]
        [(list? (car lst)) (help-flatten (car lst)) (append (cdr lst) acc)]
        [else (append (car lst) acc) (my-flatten (cdr lst))]))
    
    (define (help-flatten subLst)
      (if (null? subLst)
          (set! acc null)
          (append (car subLst) acc))
      (help-flatten (cdr subLst)))
    
  • James Combs
    James Combs about 9 years
    Im sorry, I must have misinterpreted the code that I was reading. I've been programming for a few hours, sometimes things get twisted up after awhile. I am getting a quote in my output though, what does this mean? > (my-flatten '(1 2 '(3 4) 5)) '(1 2 quote 3 4 5) -- Sorry for my bad understanding of Racket, I am pretty new to this
  • Óscar López
    Óscar López about 9 years
    @JamesCombs remove the innermost quote, that's causing the problem
  • Sylwester
    Sylwester about 9 years
    I think list? might be O(1) in #!racket but using pair? will support dotted lists as well (at least the last version) .
  • James Combs
    James Combs about 9 years
    @ÓscarLópez thanks for all of your help, if I could poke your brain just once more to fully understand the nature of this... Inside of the append function, when executing the recursion, does it execute both recursive statements at the same time, building 2 different stack frames? To me, this would be the only explanation that this works, otherwise the first recursive statement would just keep calling for the first element of the list and never reach the base case. Is this correct?
  • Óscar López
    Óscar López about 9 years
    @JamesCombs The recursive calls are executed sequentially, but append is executed only when both have returned from their respective calls. Clearly the base case is reached, why shouldn't it?. If this answer was helpful for you, please don't forget to accept it, just click on the check mark to its left ;)