我们的数据抽象有一个构造函数:
(make-city name lat lon)
创建具有给定名称、纬度和经度的城市对象。 我们还有以下选择器来获取每个城市的信息:
(get-name city) ;; Returns the city's name
(get-lat city) ;; Returns the city's latitude
(get-lon city) ;; Returns the city's longitude
我的代码:
(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)
问题是
(get-lon berkeley)
的结果是'(37)
,但我希望输出是37
,我的代码有什么问题吗?
如果您使用 Racket,则应该使用 结构 而不是列表来表示城市。
struct
创建的默认函数名称与您的不匹配,因此您可以创建别名(或直接使用结构体生成的别名):
(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)
与列表相比,这为您提供了更高效的存储空间和访问时间,让您可以轻松测试某个值是否是城市,并且
city?
返回列表的唯一方法是如果您使用列表而不是经度的数字(也有方法可以防止这种错误,例如 get-lon
子句或 struct 合同) 如果您的基于列表的布局是作业的要求并且无法更改,那么您可以考虑使用列表访问功能,例如
。比计算正确的
first
和 car
链更容易记住。cdr
他们,这样
cons
就可以 (make-object a b)
。那么 (cons a b)
将是 object-a
并且 car
将是 object-b
。这是最有效率的。您的解决方案使用正确的列表,并且两个值对象的正确列表版本是 cdr
或
(list a b)
,这使得第一个访问器相同,但最后一个访问器将是 (cons a (cons b '()))
而不是 cadr
并且总是有一个从未使用过的空列表。您可以通过像我的第一个示例一样提高对象的效率来解决此问题,或者保留您的解决方案并使用正确的访问器。您的选择!