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