bisthebis
bisthebis

Reputation: 523

contract violation in my implementation of "map"

I'm beginning in Scheme (actually, Racket with DrRacket) and I want to practice by implementing a map function (apply a function to all elements of a list), but there's something wrong that I don't understand. (I have, aside from my imperative background, a basic knowledge of haskell)

I want to translate the following piece of haskell (Just to show the algorithm) :

map f [] = []
map f x:xs = (f x) : (map f xs)

Here's my code :

(define (map f xs)

  (if (= xs '()) '() ; if list is empty, return empty list
      (cons (f (car xs)) (map f (cdr xs))))

  )

To test it, I used this :

(define (testFunction x) (+ x 1))
(define testList '(1 2 3 4 5))
(map testFunction testList)

And I get the following error :

=: contract violation
expected: number ?
given : '(1 2 3 4 5)
argument position: 1st
other arguments...:

which highlights the predicate (= xs '())

Any tips ?

Upvotes: 1

Views: 775

Answers (3)

pdoherty926
pdoherty926

Reputation: 10349

Wow - a few others already beat me to it, but I'll share my answer, anyways.

Your issue stems from your use of = to test list emptiness.

From the = in the docs:

Returns #t if all of the arguments are numerically equal, #f otherwise.

In order to get your program working, I'd suggest using equal? to test the two lists for equality or, better yet, use empty? or null? to test if xs is an empty list. (I hope you don't take offense, but I've also massaged the code into what's (arguably) more idiomatic Scheme).

(define (mymap f xs)
  (if (empty? xs)
    xs
    (cons 
      (f (car xs))
      (mymap f (cdr xs)))))

(define (test-function x) (+ x 1))
(define test-list (list 1 2 3 4))

(mymap test-function test-list)

Upvotes: 3

Alexis King
Alexis King

Reputation: 43842

The = function is specifically for equality between numbers. It has special handling for numeric values by handling comparisons between exact and inexact numbers. In general, though, for non-numeric equality, you should use the equal? predicate:

> (equal? '() '())
#t

In this particular case, as mentioned by Raghav, you can also use empty? or null? to test for the empty list (the empty? predicate is just an alias for null?).

Upvotes: 3

Ishnark
Ishnark

Reputation: 681

If you're using DrRacket, then for that condition, simply use (empty?):

(if (empty? xs)
    xs ; because xs is empty
    ...)

Upvotes: 2

Related Questions