2

I am trying to answer a scheme question, for a part of this question I have to make a list of lists:

(define (join a b (result '()))
  (cons (list a b) result))

So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:

join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))

However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?

daveyjones
  • 123
  • 3
  • 10
  • You're essentially trying to `append` `(list a b)` onto `result`, so consider how to [add element to the end of list](https://stackoverflow.com/questions/12719164/scheme-add-element-to-the-end-of-list) in scheme. – assefamaru Jan 12 '18 at 17:43

2 Answers2

4

If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:

(define (join a b (result '()))
  (append result (list (list a b))))

Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
-1

This can easily be done like this:

(define (group-by-2 lst)
  (let loop ((lst lst) (rlst '()))
    (if (or (null? lst) (null? (cdr lst)))
        (rcons->cons rlst)
        (loop (cdr lst) 
              (rcons (list (car lst)
                           (cadr lst))
                      rlst)))))

(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))

Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)

The magic functions are really not that magical:

(define rcons cons)
(define rcons->cons reverse)

So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(n²)

Sylwester
  • 47,942
  • 4
  • 47
  • 79