首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方案-逻辑操作程序

方案-逻辑操作程序
EN

Stack Overflow用户
提问于 2014-07-19 05:12:03
回答 2查看 754关注 0票数 0

我知道Scheme和其他Lisp方言包括逻辑运算符,如' and‘和'or',但是,由于我目前正在学习Scheme,所以我正在编写自己的逻辑运算符。到目前为止,我对“或”的尝试是成功的(至少就我的测试所显示的情况而言)。我的逻辑或运算符如下:

代码语言:javascript
复制
(define (logical-or a b)
   (if a true b))

我试图为'and‘编写一个逻辑运算符,它也返回一个布尔值,但是我一直被卡住了。我尝试过任意数量的组合,但我只列出以下一个,它不返回布尔值:

代码语言:javascript
复制
(define (logical-and a b)
(if a b false))

任何暗示或帮助欢迎。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-19 09:44:07

您的logical-or也不总是返回布尔值:

代码语言:javascript
复制
> (logical-or #f 2)
2

正如@leppie所说,任何不是假的(#f)在Scheme中都是正确的;尝试用内置的or函数做一些实验:

代码语言:javascript
复制
> (or 1 2)
1
> (or #f 2)
2
> (or #t 2)
#t
> (or 1 #f)
1
> (or #f #t)
#t

因此,该计划的定义是:

代码语言:javascript
复制
(define (my-or a b)
  (if a a b))

同样,对于and

代码语言:javascript
复制
> (and 1 #t)
#t
> (and 1 #f)
#f
> (and 1 2)
2
> (and #f 2)
#f
> (and #t 2)
2

所以定义是

代码语言:javascript
复制
(define (my-and a b)
  (if a b a))

如果你只想返回布尔人,那么你可以

代码语言:javascript
复制
(define (logical-or a b)
  (cond
    (a    #t)
    (b    #t)
    (else #f)))

(define (logical-and a b)
  (if a
      (if b 
          #t 
          #f)
      #f))

这适用于2个值,但是由于内置的andor操作符允许任意数量的参数(甚至0),并且只有在必要时才计算它们的参数,所以真正的定义要复杂一些。

票数 1
EN

Stack Overflow用户

发布于 2014-07-19 19:07:16

正如Uselpa的回答和leppie的评论所提到的,运算符andor不返回#t,而是返回决定表单结果的不是#f的值。因此

代码语言:javascript
复制
(and 'these 'are 'all 'true 'values)  ; ==> values
(or  'these 'are 'all 'true 'values)  ; ==> these

逻辑运算符andor是短路的,所以它们不是过程。想象一下这个过程:

代码语言:javascript
复制
(define (first-true-value lst)
  (and (pair? lst)
       (or (car lst) 
           (first-true-value (cdr lst)))))

(first-true-value '())            ; ==> #f
(first-true-value '(#f #f))       ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello

如果用版本替换andor,则过程将永远不会停止计算递归。

我们知道我们可以用and重写if(and)#t(and a)a(and a b ...)(if a (and b ...) #f)。我们可以使用最简单的Scheme宏( syntax-rules )来完成这一任务

代码语言:javascript
复制
(define-syntax logical-and 
  (syntax-rules ()
    ((logical-and) #t)
    ((logical-and a) a)
    ((logical-and a b ...)
     (if a (logical-and b ...) #f)))) 

我们也可以用同样的方式做or(or)#f(or a b ..)(if a a (or b ...))

代码语言:javascript
复制
(define-syntax logical-or 
  (syntax-rules ()
    ((logical-or) #f)
    ((logical-or a b ...) ; NB: zero elements match "b ..."
     (if a a (logical-or b ...))))) 

这个有个问题,因为它两次使用a。试试(logical-or (display "hello"))。它将评估(display "hello"),从而显示文本两次。要解决这个问题,我们需要将值包装在let中。

代码语言:javascript
复制
(define-syntax logical-or 
  (syntax-rules ()
    ((logical-or) #f)
    ((logical-or a b ...) 
     (let ((tmp a))
       (if tmp 
           tmp
           (logical-or b ...)))))) 

如果您尝试同样的,它将只显示"hello“一次。让我们尝试用新的宏编写我的初始过程:

代码语言:javascript
复制
(define (first-true-value lst)
  (logical-and (pair? lst)
               (logical-or (car lst) 
                           (first-true-value (cdr lst)))))

;; and we test them:
(first-true-value '())            ; ==> #f
(first-true-value '(#f #f))       ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24837011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档