List DrRacket中比较列表的异常行为
我正在尝试编写一个程序,检查列表列表是否具有特定的属性(对问题不重要)。在此过程中,我发现有必要生成单个给定列表的“非对角对”列表,因此我编写了一个宏,它接受一个列表并定义对列表(集合笛卡尔积的列表版本)和我将称之为该列表的“对角”(形式为List DrRacket中比较列表的异常行为,list,racket,List,Racket,我正在尝试编写一个程序,检查列表列表是否具有特定的属性(对问题不重要)。在此过程中,我发现有必要生成单个给定列表的“非对角对”列表,因此我编写了一个宏,它接受一个列表并定义对列表(集合笛卡尔积的列表版本)和我将称之为该列表的“对角”(形式为'(x x))的对)。我为实现这一点而编写的代码如下: ;;;These first two definitions are 'extended' car and cdr ;;;I only did this because the (prod a b) co
'(x x)
)的对)。我为实现这一点而编写的代码如下:
;;;These first two definitions are 'extended' car and cdr
;;;I only did this because the (prod a b) code below threw errors otherwise
(define (xcar a) (cond ((null? a) '()) ((car a))))
(define (xcdr a) (cond ((null? a) '()) ((cdr a))))
;;;This defines a pre-product, i.e. all pairs with the first element of the first list
(define (pre-prod a b)
(cond ((or (null? a) (null? b)) '())
((append (list (list (xcar a) (xcar b))) (pre-prod a (xcdr b))))))
;;;This defines the full product of the list
(define (prod a b)
(cond ((null? a) '())
((append (pre-prod a b) (prod (xcdr a) b)))))
;;;This defines the diagonal of the list
(define (diagonal a)
(cond ((null? a) '())
((append
(list (list (car a) (car a)))
(diagonal (cdr a))))))
太好了,这些代码似乎都能正常工作。接下来,我需要一个集合负号的列表版本。我发现下面的代码正是这样做的:
很酷,这似乎对它需要做的事情很好。现在我所要做的就是让DrRacket返回正确配对的列表(删除对角线)。我认为以下代码应该做到这一点:
(define (proper-pairs a) (list-minus (prod a a) (diagonal a)))
现在我在一些简单的东西上测试这个新函数,它应该返回”()
:
什么?我已经尝试了很多例子,多次修改代码,在各种列表上进行了尝试。我总是会遇到以下问题:list-minus
不会从列表列表中删除列表
问题1:为什么列表减号
在列表上显示这种异常行为,而在下面的示例中却完全按照预期工作:
> (list-minus '(1 2 3 4 5) '(x 2 4 m))
=> '(1 3 5)
问题2:如何修复列表减去代码,还是必须从头开始
问题3:在上面的第一行代码中,我必须“扩展”car
和cdr
,以确保prod
功能不会抛出错误。我做的是标准的把戏吗?我不确定我是否理解为什么它会有不同(我只是尝试了一下,因为我预感它可能会起作用)
免责声明:我不是程序员。我试图学习函数式编程作为测试各种(数学)猜想和编译一些示例的一种手段。除了我在DrRacket和旧的TI-83计算器上做过的一些非常愚蠢的小事情外,我绝对没有编写代码的经验。话虽如此,也许有必要为我“沉默”你的答案
很抱歉这么冗长,谢谢你抽出时间 问题的原因在于,与其他语言一样,球拍中的相等性由不同的运算符表示,必须根据以下条件进行选择:
必须进行比较的数据类型
比较的语义
一般的提示是,您应该使用逻辑上对任务更简单的运算符,并且可以用于某种比较
例如,您应该使用=
来eq?
to,即如果两个值是内存中的同一对象,则两个值相等eqv?
如果要检查这两个值equal?
如果要检查两个值是否为eqv?
或它们是否为相等的字符串,或者它们是否为列表等结构化数据,在结构上是等效的(请参阅),即递归等效的
例如:
(equal? '(a (b)) '(a (b))) ; => true, two different objects with the same structure
(eqv? '(a (b)) '(a (b))) ; => false, two different objects
(eq? '(a (b)) '(a (b))) ; => false, as for eqv?
(let ((x '(a (b))))
(eq? x x)) ; true, they are the same object
问题的原因在于,与其他语言一样,球拍中的相等性由不同的运算符表示,必须根据以下条件进行选择:
必须进行比较的数据类型
比较的语义
一般的提示是,您应该使用逻辑上对任务更简单的运算符,并且可以用于某种比较
例如,您应该使用=
来eq?
to,即如果两个值是内存中的同一对象,则两个值相等eqv?
如果要检查这两个值equal?
如果要检查两个值是否为eqv?
或它们是否为相等的字符串,或者它们是否为列表等结构化数据,在结构上是等效的(请参阅),即递归等效的
例如:
(equal? '(a (b)) '(a (b))) ; => true, two different objects with the same structure
(eqv? '(a (b)) '(a (b))) ; => false, two different objects
(eq? '(a (b)) '(a (b))) ; => false, as for eqv?
(let ((x '(a (b))))
(eq? x x)) ; true, they are the same object
(等式?'(1);=>#f
而(等于?'(1);=>#t
(等式?'(1);=>#f
而(等于?'(1);=>#t
我将eq?
更改为equal?
现在它的运行方式与我想要的完全一样!非常感谢你非常清楚和有用的回答!我将eq?
更改为equal?
,现在它的运行方式也完全符合我的要求!非常感谢你非常清楚和有用的回答!
(equal? '(a (b)) '(a (b))) ; => true, two different objects with the same structure
(eqv? '(a (b)) '(a (b))) ; => false, two different objects
(eq? '(a (b)) '(a (b))) ; => false, as for eqv?
(let ((x '(a (b))))
(eq? x x)) ; true, they are the same object