【问题标题】:(Scheme) Check a list of item are all satisfied an logical relation(方案)检查项目列表是否都满足逻辑关系
【发布时间】:2023-04-05 17:30:02
【问题描述】:

我目前正在学习 Scheme,遇到一个问题,其描述如下:定义并实现一个函数,该函数采用逻辑运算符 check 和列表 xs 之类的东西,然后检查 (check a b) 是否评估为 true对于列表xs中的所有两个靠近元素ab

下面的一些例子:

(check < '(15 16 17 18)) 
#t

(check > '(5)) 
#t

(check > '()) 
#t

(check (lambda (a b) (eq? b (+ a 1))) '(11 12 13))
#t

(check eq? '(4 4 5))
#f

在我看来,我认为这个类似于检查列表的问题是否按升序排序,但实现可能会有一些差异。 我打算定义一个与foldl 相关的递归函数并进行一些条件检查,但我的问题是如何检测逻辑运算符是什么以及它们如何在我的代码中工作,所以任何人都可以帮忙吗?提前谢谢你。

【问题讨论】:

  • 这里要做的事情是尽早摆脱失败。你可以用 foldl 做到这一点吗?
  • “如何检测逻辑运算符是”有什么要检测的?你得到它,作为一个论据。您将其称为(check a b),它会为您返回#f#t。是的,如果你可以编写is-sorted 谓词,这本质上是一回事。啊哈,我明白你的困惑在哪里。您将函数及其参数命名为相同的名称,check。将其重命名为(check-list &lt; '(15 16 17 18)),并调用(check 15 16)(check 16 17) 等:(define (check-list check list) ...)。那么check 可能是(lambda (a b) (eq? b (+ a 1)))

标签: functional-programming scheme racket fold


【解决方案1】:

函数可以返回 true 的情况有两种,即空列表和具有单个元素的列表。您使用null? 检查空列表。您需要首先检查列表是否为空,如果不是,则其子列表是否为空(在这种情况下,必然只有一个元素)。如果这些列表中的任何一个为空,则谓词通常会返回 true。

否则,在一般情况下,仅当 check 适用于元素对(该对存在,因为我们排除了大小为 0 和 1 的列表)、 如果子列表也满足谓词。

(define (every-pair-check? check xs)
  (or (null? xs)
      (null? (cdr xs))
      (and (check (car xs) (cadr xs))
           (every-pair-check? check (cdr xs)))))

【讨论】:

    【解决方案2】:
    (define (check-every? check-operator lst)
      (cond ((or (null? lst) (= (length lst) 1)) #t)
            ((check-operator (car lst) (cadr lst)) (check-every? check-operator (cdr lst)))
            (else #f)))
    

    这会在第一次#f 测试发生后立即停止,因此很有效。

    我想通过这个来保存一些支票:

    ;; cave! Erroneous code!!
    (define (check-every? check-operator lst)
      (cond ((and (null? (cdr lst)) (<= (length lst) 1)) #t)
            ((check-operator (car lst) (cadr lst)) (check-every? check-operator (cdr lst)))
            (else #f)))
    

    这种策略适用于 common lisp,因为(cdr '()) 在 common lisp 中返回 '()。但是在 Racket/Scheme 中,这会返回一个错误。多么混乱!感谢提醒我,@coredump!

    我的想法是:

    (null? (cdr lst))(or (null? lst) (= (length lst) 1)) 的黑客, 但是,如果lst 的一个元素是'(),那么我们就有麻烦了。 但是对于正常的号码列表,它可以工作。否则,应该使用更长的测试。现在我更正为(and (null? (cdr lst)) (&lt;= (length lst) 1)), 其中 - 由于 and 的短路 - 仅测试 (null? (cdr lst)),但如果为真,则另外检查 lst 的长度是 1 还是零。只有这样,它才会在这种情况下返回 #t。所以这个表格抓住了这种情况,即lst 可以包含'() 作为一个元素,而不是在最后一个位置,通过仍然最小化每个周期的测试数量。

    但是好吧,因为这在 Racket 中是不可能的,所以第一个版本是最短的......

    【讨论】:

    • Scheme 中的 cdr 需要一个 cons 单元格;在空列表上使用它是错误的。
    • 啊!谢谢@cordump。这种行为多么令人困惑......然后我必须把它改回来......
    猜你喜欢
    • 2013-12-14
    • 1970-01-01
    • 2014-04-08
    • 2018-04-11
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多