【问题标题】:A function which will determine that if a passed in list follows an A B pattern一个函数,它将确定传入的列表是否遵循 A B 模式
【发布时间】:2013-10-16 00:43:31
【问题描述】:
(define fun4

 (lambda ( ls)

(cond ((null? ls ) #f)

 (cons (((eqv? 'a (car ls))) && ((eqv? 'b (cdr ls)))))

(else (pattern2 cdr ls)))))

在此显示错误 - 过程应用程序:预期过程,给定:#t(无参数), 我的代码中有什么错误。逻辑没问题???

【问题讨论】:

  • 有一个else,但我没有看到if...此外,A B 模式是什么?
  • 它的方案..方案博士。在此条件中用作 ifelse 语句,A B 模式是重复的列表的模式,如 (A B A B)

标签: list scheme racket lambda


【解决方案1】:

您的解决方案中有很多很多错误。让我们看看每个条件有什么问题:

  1. 递归的基本情况(空列表)是错误的:空列表是递归的出口,这意味着该列表被正确遍历并且遵循模式
  2. 缺少另一个基本情况:如果列表只有一个元素怎么办?
  3. 如果模式不成立,我们必须立即返回#f,注意我们如何使用cadr来访问第二个元素,因为&&在Scheme中不起作用,你必须使用and用于逻辑 and 操作。此外,每个测试周围都有不必要的错误括号(顺便说一句:那些是导致“预期过程”错误的括号)
  4. 仅当上述条件都不成立时,我们才会推进递归,并且我们通过使用cddr两个 元素向下移动到列表的下方来实现。此外,您必须调用 fun4 来推进递归,而不是 pattern2

这是解决问题的正确方法,请注意上述问题是如何解决的:

(define fun4
  (lambda (ls)
    (cond ((null? ls) #t)                                       ; 1
          ((null? (cdr ls)) #f)                                 ; 2
          ((not (and (eq? 'a (car ls)) (eq? 'b (cadr ls)))) #f) ; 3
          (else (fun4 (cddr ls))))))                            ; 4

始终测试您的程序,以上将正常工作:

(fun4 '())
=> #t
(fun4 '(a))
=> #f
(fun4 '(a b))
=> #t
(fun4 '(a b a))
=> #f
(fun4 '(a b a b))
=> #t

最后一点,如果空列表不应该遵循该模式,则在调用 fun4 之前检查它,如果初始输入列表为空,则返回 #f

【讨论】:

  • 非常感谢 Oscar Lopez.. 很好的解决方案
【解决方案2】:
(define fun 
  (lambda (ls)
    (cond ((null? ls) #t)
          ((and (eq? (car ls) 'a)       ; the first item is a
                (list? (cdr ls))        ; the rest of the list
                (not (null? (cdr ls)))  ; which is not null
                (eq? (cadr ls) 'b)      ; and it starts with b
                (fun (cddr ls))) #t)    ; and the rest of the expression is 
          (else #f))))                  ; also in the A B format

跑步:

> (fun '(a b a b))
#t
> (fun '(a b a))
#f
> (fun '(a b))
#t
> (fun '(a))
#f
> (fun '())
#t
> 

【讨论】:

  • 列表的 cdr 不是第二项,而是列表的其余部分。 cadr 是列表的第二项。
  • @JoshuaTaylor 1. 这里没有矛盾:第二项是“列表的其余部分”。 2. 如果我不知道 - 我为什么要检查 (list? (cdr ls)) ? ;) 3. 我更改了措辞以防止误解
  • code 是对的,但原始 cmets 说“第二项是一个列表 \,它不是 null \,它以 b \ 开头,其余的表达式也是 AB 格式”,它将描述 ([A (B . _)]*) 形式的列表,例如 (A (B C) A (B . X) A (B (G H))),这是不正确的。正如我所说,代码 是正确的;只有 cmets 具有误导性。典型别名包括(define second cadr)(define rest cdr),但不是 (define second cdr)
  • @JoshuaTaylor 因为你坚持:cons 被定义为一个元组,car 作为第一项,cdr 作为第二项。 cdr 以递归方式定义。因此,您可以将第二项称为“列表的其余部分”,这是正确的。我将其称为“第二项”,这也是正确的。我更改了措辞,因为您不理解我写的内容,并且我希望我的 cmets(以及代码)尽可能清晰。这并不意味着我写的是错误的。
  • 我明白你的意思,但是根据 OP 的代码(以及一般在 Stack Overflow 上),其他 读者可能没有那么多 Lisp 经验。这是我的意见(这是一个意见问题),在编写处理列表“第二”的函数时,建议使用“列表的第二个元素”而不是“cons 单元格的第二部分(其中,顺便说一句,用于编码列表)。”我认为这与任务“检查列表的第一个元素是否为 A,其第二个元素是否为 B,以及之后列表的其余部分是否具有相同的形式”这一任务的随意描述非常吻合。
【解决方案3】:

如此多的车轮改造。只需使用 SRFI 1!

(require srfi/1)
(define (fun4 lst)
  (every eq? lst (circular-list 'a 'b)))

(这是在(a b a) 应该有效而不是无效的假设下运行的。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2019-06-04
    • 2014-02-17
    • 2022-10-13
    相关资源
    最近更新 更多