Josue Nunez
Josue Nunez

Reputation: 21

How can I fix my Scheme error: Argument #1 '()' to 'car' has wrong type (empty-list)

Write a function that takes a list and a length as input and returns two lists: (1) The first length elements of the input list, and (2) the remainder of the input list. Hint: Use a helper method with an "accumulator" parameter. I'm stuck guys and could really use some help.

I keep getting error when I try to do (split-list '(a b c d e f g) 7) which is the number equal to length otherwise any number less than than that does what its supposed to do :

Argument #1 '()' to 'car' has wrong type (empty-list)

(split-list '(a b c d e f g) 0) should return '(() (a b c d e f g))

(split-list '(a b c d e f g) 1) should return '((a) (b c d e f g))

(split-list '(a b c d e f g) 3) should return '((a b c) (d e f g))

(define (split-list lst length) 
    (define(split-list-head accum length)
        (if (= length 0)
            (cdr '(accum))
            (cons (car accum) (split-list-head (cdr accum)(- length 1)))
        )
    )
    
    (define(split-list-tail accum length)
        (if (= length 0)
            (cons (car accum)(cdr accum))
            (split-list-tail (cdr accum)(- length 1))
        )
    )

    (if (eq? length 0) 
        (append(list (list))(list lst))
        (append(list(split-list-head lst length)) (list(split-list-tail lst length)))
    )
)

Upvotes: 0

Views: 550

Answers (2)

Will Ness
Will Ness

Reputation: 71065

Try this. It makes use of three accumulating parameters. A subtraction is also kind of accumulation.

(define (split n xs k)
  (define (loop xs n k)
    (if
      (and (> n 0) (not (null? xs)))
      (loop (cdr xs) (- n 1) 
             (lambda (a b) (k (cons (car xs) a) b)))
      (k '() xs)))
  (loop xs n k))

Can you see how it is to be called?

Can you explain how it works?

Or a bit shorter,

(define (split n xs k)
  (define ((+ f a) b) (f (cons (car a) b)))
  (define (loop xs n k)
    (if
      (and (> n 0) (not (null? xs)))
      (loop (cdr xs) (- n 1) (+ k xs))
      ((k '()) xs)))
  (loop xs n k))

Can you find a way how should this function be called? I'll give you a hint, how should this function

(define ((add a) b) (list a b))

be called?

Upvotes: 0

Francis King
Francis King

Reputation: 1732

Unless you are particularly attached to GNU Scheme, I would consider moving to Dr Racket.

Although it was written for a similar language called Racket, it can be set up to run vanilla Scheme, by putting in a first line #lang scheme

The nice about Dr Racket is that it has a very nice debugger.

My code, with the #lang line at the start, and the erroring line at the bottom:

#lang scheme

(define (split-list lst length) 
    (define(split-list-head accum length)
        (if (= length 0)
            (cdr '(accum))
            (cons (car accum) (split-list-head (cdr accum)(- length 1)))
        )
    )

    (define(split-list-tail accum length)
        (if (= length 0)
            (cons (car accum)(cdr accum))
            (split-list-tail (cdr accum)(- length 1))
        )
    )

    (if (eq? length 0) 
        (append(list (list))(list lst))
        (append(list(split-list-head lst length)) (list(split-list-tail lst length)))
    )
)

(split-list '(a b c d e f g) 7)

If I just run the code, it highlights the error in split-list-tail, where car causes a contract violation. It also shows the call sequence.

enter image description here

That's probably enough to identify the fault, but I can also run the debugger. By clicking on the Debug button I move to the debug mode. By moving the mouse pointer over a parenthesis, and right clicking, I can enable or disable a pause at this point - show by a pink circle. The variables are shown on the right hand side. When I run the code in the debugger, variable accum is empty, hence car accum fails.

enter image description here

My suggestion is that you use pair? or null? to test accum before calling car on it.

Upvotes: 1

Related Questions