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

Scheme购物车计价程序调用add-cart报contract violation错误求解

问题原因

你的代码报错核心是对Scheme中quote(即语法里的单引号')的求值规则理解有误:

  • 你调用时传入的'(milk chicken carrots)是符号字面量列表,等价于(list 'milk 'chicken 'carrots)。单引号包裹的结构不会对内部标识符做求值替换,列表里存的是milk/chicken/carrots三个符号本身,根本不是你之前用define绑定的2.99、7.99、1.99这些数值。
  • 你写的add-cart函数默认列表元素直接是数字,直接取(car x)传入加法运算,递归到最后一个元素时拿到的是符号carrots,不满足+运算符要求参数为数字的契约,因此触发报错。
修复方案

不推荐用顶层define零散绑定商品价格的写法,这种方式耦合度高、扩展性差,也不方便做商品名到价格的映射查询。更符合Scheme习惯的实现是用关联列表(alist)统一存储商品价格映射,代码如下:

#lang scheme
;; 关联列表存储商品符号与对应价格的键值对
(define price-table
  '((milk . 2.99)
    (chicken . 7.99)
    (carrots . 1.99)))

;; 辅助函数:根据商品符号查询对应价格,不存在则抛出错误
(define (get-price item)
  (cond
    [(assq item price-table) => cdr]
    [else (error "无效商品名:" item)]))

;; 修正后的计价递归函数
(define (add-cart cart)
  (if (empty? cart)
      0
      (+ (get-price (car cart))
         (add-cart (cdr cart)))))

;; 测试调用,传参格式和你原来的写法完全一致
(add-cart '(milk chicken carrots)) ; 运行返回正确结果12.97

如果你一定要保留最开始逐个define绑定商品价格的写法,理论上可以通过eval对取到的符号做顶层作用域求值来实现,但这种写法效率低、容易出作用域问题,完全不推荐在作业或正式代码里使用。

新手提示
  • Scheme中单引号包裹的所有字面量都不会触发内部标识符求值,写的时候要明确区分「要被求值的变量」和「作为数据存在的符号/字面量列表」。
  • 遇到contract violation类的类型报错时,优先检查你传入运算的参数实际类型,顺着递归/调用链排查值的传递过程,很容易定位错位点。
  • 存储键值映射类的数据优先用关联列表、哈希表这类专用结构,不要把数据零散绑定为顶层变量,后续增删商品、做优惠逻辑都会方便很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:09:18