DrRacket 中的异常行为比较列表
Anomalous Behavior Comparing Lists in DrRacket
我正在尝试编写一个程序来检查列表列表是否具有特定的 属性(对问题不重要)。在此过程中,我发现有必要生成单个给定列表的 "non-diagonal pairs" 列表,因此我编写了一个宏,它接受一个列表并定义了两个对列表(集合的笛卡尔积的列表版本) 以及我将称之为该列表的 "diagonal" 的内容('(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))))))
太好了,该代码似乎都按照我想要的方式工作。接下来,我需要使用 set-minus 的列表版本。我在 an answer here:
中找到了以下代码来执行此操作
;;;Returns #t if x is an element of lst and #f otherwise
(define (element? x lst)
(cond ((null? lst) #f)
((eq? x (car lst)) #t)
(#t (element? x (cdr lst)))))
;;;Takes list a and removes all elements of list b from it
(define (list-minus a b)
(cond ((null? a) '())
((element? (car a) b)
(list-minus (cdr a) b))
(#t (cons (car a) (list-minus (cdr a) b)))))
太棒了,这对于它需要做的事情来说似乎工作得很好。现在我所要做的就是让 DrRacket 到 return 适当对的列表(删除对角线)。我认为下面的代码应该可以做到这一点:
(define (proper-pairs a) (list-minus (prod a a) (diagonal a)))
现在我在一些简单的地方测试这个新功能,它应该 return '()
:
> (proper-pairs '(1))
=> '((1 1))
什么?我已经尝试了很多示例,多次修改代码,并在各种列表列表上进行了尝试。我总是遇到以下问题:list-minus
不会从列表列表中删除列表。
问题 1: 为什么 list-minus
在列表的列表中表现出这种异常行为,同时完全按预期处理以下示例:
> (list-minus '(1 2 3 4 5) '(x 2 4 m))
=> '(1 3 5)
问题2:如何修复list-minus
代码,还是需要从头开始?
问题 3: 在上面代码的第一行中,我必须 "extend" car
和 cdr
以确保prod
函数不会抛出错误。我做的是标准把戏吗?我不确定我是否理解它为什么会有所不同(我只是尝试了一下,因为我有预感它可能会起作用)。
免责声明:我不是程序员。我正在尝试学习函数式编程,以此作为测试各种(数学)猜想和编写一些示例的方法。除了我在 DrRacket 和旧的 TI-83 计算器上编写的一些非常愚蠢的小代码外,我完全没有编写代码的经验。话虽这么说,可能有必要 "dumb-down" 你对我的回答。
啰嗦了,谢谢您的宝贵时间!
问题是由于 Racket 中的相等性与其他语言一样,用不同的运算符表示,必须根据以下条件进行选择:
必须比较的数据类型,
比较的语义。
一般的提示是,您应该使用逻辑上更简单的运算符来完成任务,并且可以用于特定的比较。
例如,你应该使用=
到compare numbers; eq?
to compare objects for identity i.e. two values are equal if the are the same object in memory; eqv?
if you want to check that two values are the same object in memory or are equal numbers or equal characters; equal?
if you want to check if two values are eqv?
or if they are equal strings, or if they, being structured data like lists, are structurally equivalent (see the manual),即递归等价。
例如:
(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
我正在尝试编写一个程序来检查列表列表是否具有特定的 属性(对问题不重要)。在此过程中,我发现有必要生成单个给定列表的 "non-diagonal pairs" 列表,因此我编写了一个宏,它接受一个列表并定义了两个对列表(集合的笛卡尔积的列表版本) 以及我将称之为该列表的 "diagonal" 的内容('(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))))))
太好了,该代码似乎都按照我想要的方式工作。接下来,我需要使用 set-minus 的列表版本。我在 an answer here:
中找到了以下代码来执行此操作;;;Returns #t if x is an element of lst and #f otherwise
(define (element? x lst)
(cond ((null? lst) #f)
((eq? x (car lst)) #t)
(#t (element? x (cdr lst)))))
;;;Takes list a and removes all elements of list b from it
(define (list-minus a b)
(cond ((null? a) '())
((element? (car a) b)
(list-minus (cdr a) b))
(#t (cons (car a) (list-minus (cdr a) b)))))
太棒了,这对于它需要做的事情来说似乎工作得很好。现在我所要做的就是让 DrRacket 到 return 适当对的列表(删除对角线)。我认为下面的代码应该可以做到这一点:
(define (proper-pairs a) (list-minus (prod a a) (diagonal a)))
现在我在一些简单的地方测试这个新功能,它应该 return '()
:
> (proper-pairs '(1))
=> '((1 1))
什么?我已经尝试了很多示例,多次修改代码,并在各种列表列表上进行了尝试。我总是遇到以下问题:list-minus
不会从列表列表中删除列表。
问题 1: 为什么 list-minus
在列表的列表中表现出这种异常行为,同时完全按预期处理以下示例:
> (list-minus '(1 2 3 4 5) '(x 2 4 m))
=> '(1 3 5)
问题2:如何修复list-minus
代码,还是需要从头开始?
问题 3: 在上面代码的第一行中,我必须 "extend" car
和 cdr
以确保prod
函数不会抛出错误。我做的是标准把戏吗?我不确定我是否理解它为什么会有所不同(我只是尝试了一下,因为我有预感它可能会起作用)。
免责声明:我不是程序员。我正在尝试学习函数式编程,以此作为测试各种(数学)猜想和编写一些示例的方法。除了我在 DrRacket 和旧的 TI-83 计算器上编写的一些非常愚蠢的小代码外,我完全没有编写代码的经验。话虽这么说,可能有必要 "dumb-down" 你对我的回答。
啰嗦了,谢谢您的宝贵时间!
问题是由于 Racket 中的相等性与其他语言一样,用不同的运算符表示,必须根据以下条件进行选择:
必须比较的数据类型,
比较的语义。
一般的提示是,您应该使用逻辑上更简单的运算符来完成任务,并且可以用于特定的比较。
例如,你应该使用=
到compare numbers; eq?
to compare objects for identity i.e. two values are equal if the are the same object in memory; eqv?
if you want to check that two values are the same object in memory or are equal numbers or equal characters; equal?
if you want to check if two values are eqv?
or if they are equal strings, or if they, being structured data like lists, are structurally equivalent (see the manual),即递归等价。
例如:
(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