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

Scheme面向消息关联数组实现:如何返回修改后的有状态函数实例

问题根因
  • 状态变量位置错误:存储键值对的lst变量定义在了dispatch函数内部,每次调用dispatch处理消息时都会创建一个全新的空lst,处理完的修改随调用结束直接销毁,无法持久保留状态。正确的做法是把lst放到make-empty-as的作用域内、dispatch的外层,让dispatch作为闭包捕获这个持久化的状态变量。
  • 键值对前置逻辑错误:原实现用(append lst (list arg))实现cons,这是把新键值对追加到列表末尾,不符合「前置」的要求,应该改为(cons arg lst)直接把新配对放到列表头部。
修正后的可变对象实现

符合你需要的「修改实例变量后返回对象自身」的面向对象风格:

(define (make-empty-as)
  ;; 状态变量放到dispatch外层,作为闭包的持久状态
  (let ((lst '()))
    (define (dispatch msg arg)
      (cond
        ((eq? msg 'cdr)
         (if (not (null? lst))
             (set! lst (cdr lst)))
         ;; 返回当前dispatch,即修改后的对象自身
         dispatch)
        ((eq? msg 'cons)
         (if (= (length arg) 2)
             ;; 新键值对前置到列表头部
             (set! lst (cons arg lst)))
         dispatch)
        ;; 新增调试消息,可查询内部存储的配对列表
        ((eq? msg 'get-list)
         lst)
        (else (error "Don't understand " msg))))
    dispatch))
测试验证
(define a1 (make-empty-as))
(define a2 (a1 'cons '(b 2)))
(define a3 (a2 'cons '(d 4)))
(define a4 (a3 'cons '(c 5)))
(define a5 (a4 'cons '(a 6)))
(define a6 (a5 'cons '(c 4)))
(define a7 (a6 'cons '(b 7)))
(define a8 (a7 'cons '(a 1)))

;; 验证a8的内部状态,输出符合要求的配对列表
(a8 'get-list 'dummy)
;; 输出:((a 1) (b 7) (c 4) (a 6) (c 5) (d 4) (b 2))

;; 验证cdr功能
(define a9 (a8 'cdr 'dummy))
(a9 'get-list 'dummy)
;; 输出:((b 7) (c 4) (a 6) (c 5) (d 4) (b 2))
可选不可变实现思路

如果作业要求符合函数式范式、不修改原对象、返回全新的关联数组,可以调整为每次处理cons/cdr消息时,新建一个关联数组实例,把计算后的新列表作为初始状态传入即可,不需要修改当前对象的状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 23:45:09