sicp-lang/sicp

filter: contract violation expected: list?

morbidCode opened this issue · 3 comments

There is something odd about filter when the sicp package is required. Here's my code.

(require sicp)
(print-as-expression #f) ; for printing lists
(#%require r5rs/init) ; for printing lists
(filter (lambda (x) #t) (list ))
()
(filter (lambda (x) #t) (list 1))
; filter: contract violation
; expected: list?
; given: (1)
; [,bt for context]

I don't know what caused filter to act so strangely...

The problem is that lists in Racket and Scheme (SICP/R5RS) are different.
Racket lists are immutable and Scheme lists are mutable.

In #lang sicp and #lang r5rs lists are built using mcons (short for mutable cons) and the empty list. In Racket lists are built using cons and the empty list.

Therefore filter from racket/list doesn't work with list created by Scheme.
Since filter is not part of R5RS the easiest is to define your own version:

#lang sicp
(define (filter pred xs)
  (if (null? xs)
      '()
      (if (pred (car xs))
          (cons (car xs) (filter pred (cdr xs)))
          (filter pred (cdr xs)))))

I forgot to write that (require sicp) imports the list used by SICP/R5RS so the (list 1) in your example produces a list built with mcons.

Got it. Thanks.