由于语义模型根本不同,Lisp cons 单元不能直接建模为 Tcl 值。Lisp 使用一个模型,值可以直接更新。该值是存储单元。Tcl 使用不同的模型,其值在概念上是不可变的,并且恰好位于周围的任何“1 2 3 4”之间在原则上没有区别;Tcl 中的可变实体是变量带有名称(名称字符串本身是不可变的,当然……)这种不变性在简单值的级别上是有意义的,但它也扩展到 Tcl 的列表和字典;变异操作要么返回一个新值,要么更新一个变量。(实现比这更有效,使用写时复制策略来保留不变性的语义模型,同时能够在实际已知语义等价时通过值本身的突变来实现事物。)
因此,您必须将可更新的 cons 单元格构造为变量。您可以这样做:
proc cons {a b} {
    global gensym cons
    set handle G[incr gensym]
    set cons($handle) [list $a $b]
    return $handle
}
proc car {handle} {
    global cons
    return [lindex $cons($handle) 0]
}
proc cdr {handle} {
    global cons
    return [lindex $cons($handle) 1]
}
proc setCar {handle value} {
    global cons
    lset cons($handle) 0 $value
}
# Convenience procedures
proc makeFromList args {
    set result "!nil"
    foreach value [lreverse $args] {
        set result [cons $value $result]
    }
    return $result
}
proc getAsList {handle} {
    set result {}
    while {$handle ne "!nil"} {
        lappend result [car $handle]
        set handle [cdr $handle]
    }
    return $result
}
set a [makeFromList 1 2 3 4]
# Use some local context; Tcl doesn't have anything exactly like Lisp's "let"
apply {a {
    set b $a
    set a [cdr [cdr $a]]
    setCar [cdr $b] "b"
    setCar [cdr $a] "d"
    puts [getAsList $a]
}} $a
puts [getAsList $a]
这会产生预期的输出(鉴于 Lisp 和 Tcl 对如何格式化列表有不同的想法)。