【问题标题】:How do I use and/or instead of if/cond?如何使用和/或代替 if/cond?
【发布时间】:2016-01-26 18:46:11
【问题描述】:

我是 Scheme 编程的新手,我已经完成了这项任务,但我不知道如何正确工作。我应该用一个参数(一个数字)定义一个过程。如果数字为正,我希望返回 1,如果数字为负,则返回 -1,如果为 0,则返回 0,仅使用和/或。 if 和 cond 是不允许的。我只返回 #t#f,但你知道这不是我想要的。任何帮助或指针表示赞赏

【问题讨论】:

  • 显示您的代码。到目前为止您尝试过什么?

标签: scheme lisp r5rs


【解决方案1】:

您可以通过查看以下等价来解决您的问题,当每个 expj 的值与 #f 不同时有效

(cond (test1 exp1)         (or (and test1 exp1)
      (test2 exp2)             (and test2 exp2)
      ...               ≡      ...
      (testn expn)             (and testn expn)
      (else expn+1))           expn+1)

由于获取数字符号的函数可以简单地写成这样:

(define (sign x)
  (cond ((> x 0) +1)
        ((< x 0) -1)
        (else 0)))

应用上述等式后,由于每个结果都是整数,不同于#f,因此该函数等于另一个答案中提出的解决方案:

(define (sign x)
  (or (and (> x 0) +1)
      (and (< x 0) -1)
      0))

那么,上述等价的原因是什么?这取决于and 依次评估其参数这一事实;只要其中一个是#f,它就会通过返回#f 停止,否则返回它的last 参数(这解释了(and testj expj) 的单个分支);而or 依次评估其参数;一旦其中一个是 not #f,它就会停止返回它,否则返回它的 last 参数(这解释了链 (or (and ...) (and ...) ... expn+1))。

【讨论】:

  • 只有当所有的 expN 都为真时,这个等价才是正确的。
【解决方案2】:
(define test 
    (lambda (n)
        (or (and (< n 0) -1)
            (and (= n 0) 0)
            1)))

诀窍的一部分是理解 and,如果一切都评估为真,将返回它评估的最后一个项目,而 or 将返回第一个成功评估的项目为真。另一部分是意识到除了#f 之外的所有内容都被认为是“真实的”。

【讨论】:

    【解决方案3】:

    and 的转换可以在报告中看到,但不包括实际的宏基本上是这样的:

    ; only one argument
    (and a) ; ===>
    a
    
    ; one of more
    (and a b ...) ; ==>
    (if a
        (and b ...)
        #f)
    

    所有参数的计算结果必须为正值,最后一个值是结果,否则 #f。它会短路,所以当某些东西是 #f 时,其余的表达式永远不会被评估。

    对于or 是这样的:

    (or a) ; ==>
    a
    
    (or a b ...) ; ==>
    (let ((a-value a))
      (if a-value
          a-value
          (or b ...)))
    

    返回第一个不等于 #f 的参数。如果所有值都是#f,则最后一个#f 将是结果。

    如果你愿意的话:

    (if a b c)                 ; ==>
    
    (let ((tmpa a))            
      (or (and atmpa b)        
          (and (not atmpa) c)) ; not part only important if b can be #f
    

    我使用let 来防止多次计算同一个表达式。例如。如果你有一个打印类似(begin (display "hello") #f) 的东西,或者这是一个昂贵的计算,那么它是必要的,否则你可以用表达式替换变量。例如。最后一个会变成:

    (or (and a b)
        (and (not a) c))
    

    没有临时变量的变回变成:

    (if (if a b #f)
        (if a b #f)
        (if (not a) c #f))
    

    如果 b 是 #f 值,那么结果是 #f,因为最后一个 if。因此每次a 为真b 就是结果。每次都是假的,c 就是答案。因此

    (if a b c)
    

    假设你想返回列表中的第一个真值。

    (define (first-true lst)
      (and (not (null? lst))
           (car lst)
           (first-true (cdr lst))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-27
      • 2016-06-21
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-22
      • 2021-08-26
      相关资源
      最近更新 更多