Our data abstraction has one constructor:
(make-city name lat lon)
Creates a city object with the given name, latitude, and longitude. We also have the following selectors in order to get the information for each city:
(get-name city) ;; Returns the city's name
(get-lat city) ;; Returns the city's latitude
(get-lon city) ;; Returns the city's longitude
My code:
(define (make-city name lat lon)
(cons name (cons lat (cons lon null))))
(define (get-name make-city)
(car make-city))
(define (get-lat make-city)
(car (cdr make-city)))
(define (get-lon make-city)
(cdr (cdr make-city)))
(define berkeley (make-city 'Berkeley 122 37))
(get-name berkeley) 'Berkeley
(get-lat berkeley) 122
(get-lon berkeley) '(37)
The problem is that the result of (get-lon berkeley)
is '(37)
but i want the output to be 37
, what's wrong with my code?
If you're using Racket, you should use a structure instead of a list to represent the city. The default function names created by struct
don't match yours, so you can make aliases (Or use the struct-generated ones directly):
(struct city (name lat lon)
#:transparent
#:extra-constructor-name make-city)
(define get-name city-name)
(define get-lat city-lat)
(define get-lon city-lon)
That gives you more efficient storage space and access time compared to a list, gives you city?
to easily test if a value is a city, and the only way get-lon
will return a list is if you create the city with a list instead of a number for the longitude (And there are ways to prevent that mistake, too, like a #:guard
clause or struct contracts)
If your list-based layout is a requirement of an assignment and can't be changed, though, you might consider list access functions like first
. Easier to remember than figuring the correct chain of car
s and cdr
s.