gpt4 book ai didi

lisp - 在 Tcl 中模拟 lisp cons 单元

转载 作者:太空宇宙 更新时间:2023-11-03 18:38:08 25 4
gpt4 key购买 nike

lisp 中的列表是一系列cons 单元格,但在Tcl 中,列表是用空格分隔元素的字符串。要将代码从 lisp 翻译成 tcl,可以简单地获取 lisp 列表并将它们翻译成 Tcl 列表。然而,这会遇到麻烦,因为副作用单元不会出现在 Tcl 代码中。例如,在 lisp 中考虑以下代码:

(setq a (list 1 2 3 4))
(let ((b a)
(a (cddr a)))
(declare (special a b))
(setf (cadr b) ‘b)
(setf (cadr a) ‘d)
(print a))
(print a)

;; Results in:
(3 d)
(1 b 3 d)

是否有 Tcl 包可以更好地模拟 Tcl 中的 lisp 列表?这样的包是否可以轻松转换为常规 Tcl 列表?

使用这样的包,上面的代码在 Tcl 中看起来像什么?

最佳答案

由于根本不同的语义模型,Lisp cons 单元不能直接建模为 Tcl 值。 Lisp 使用一种模型,值可以直接更新;该值是存储单元。 Tcl 使用了一个不同的模型,其值在概念上是不可变的,并且原则上任何“1 2 3 4”与其他任何“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 对如何格式化列表有不同的想法)。

关于lisp - 在 Tcl 中模拟 lisp cons 单元,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3680980/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com