我如何使用和/或代替if / cond?

时间:2016-01-26 18:46:12

标签: scheme lisp r5rs

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

3 个答案:

答案 0 :(得分:3)

如果您查看以下等效项,则可以解决您的问题;当每个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停止,否则返回其最后参数(这解释了单个分支(and testj expj));而or依次评估其论点;只要其中一个 #f,它就会通过返回它停止,否则返回其 last 参数(这解释了链(or (and ...) (and ...) ... expn+1) )。

答案 1 :(得分:1)

(define test 
    (lambda (n)
        (or (and (< n 0) -1)
            (and (= n 0) 0)
            1)))

部分技巧是理解,如果一切评估为true,将返回它评估的最后一项,而将返回成功评估的第一项为真。另一部分是认识到除了#f之外的所有事情都被认为是真实的。&#34;

答案 2 :(得分:0)

报告中可以看到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))))