You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义城市ADT中get-lon返回列表而非数值的问题排查

城市ADT中get-lon返回列表而非数值的问题排查

问题重现

我们定义了城市抽象数据类型(ADT),包含构造器make-city和选择器get-name、get-lat、get-lon,代码实现如下:

(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,需要排查代码错误。

错误原因

问题出在构造器的结构设计和选择器的匹配逻辑不统一:

  • 构造器make-city中,(cons lon null)等价于(list lon),把经度值包装成了一个单元素列表,最终生成的城市结构是(Berkeley . (122 . (37 . ()))),此时(cdr (cdr berkeley))取到的是(37 . ()),也就是显示为'(37)的列表。
  • 选择器get-lon直接取(cdr (cdr make-city)),拿到的是这个单元素列表,而非列表里的数值37。

修正方案

有两种可行的修正方式,推荐第一种(更符合Scheme配对结构的简洁设计):

方案一:修正构造器,让经度作为原子值存储

调整make-city的实现,去掉最后一层cons和null,让经度直接作为配对结构的最后一个元素:

(define (make-city name lat lon)
  (cons name (cons lat lon))) ; 直接将lon作为最终的cdr部分

(define (get-name city)
  (car city))

(define (get-lat city)
  (car (cdr city)))

(define (get-lon city)
  (cdr (cdr city))) ; 此时直接取到的就是lon的数值

(define berkeley (make-city 'Berkeley 122 37))
(get-name berkeley) ; 输出 'Berkeley
(get-lat berkeley)  ; 输出 122
(get-lon berkeley)  ; 输出 37

方案二:保留原构造器,修正选择器逻辑

如果需要保留原构造器的结构,修改get-lon,从单元素列表中取出数值:

(define (make-city name lat lon)
  (cons name (cons lat (cons lon null))))

(define (get-name city)
  (car city))

(define (get-lat city)
  (car (cdr city)))

(define (get-lon city)
  (car (cdr (cdr city)))) ; 取列表的第一个元素(即数值37)

(define berkeley (make-city 'Berkeley 122 37))
(get-lon berkeley) ; 输出 37

内容的提问来源于stack exchange,提问作者Proteus Yi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:34:50