计划 - 如果有结果的几个操作

时间:2016-02-04 09:50:37

标签: if-statement scheme racket

我非常简要地研究了Scheme并想知道是否有办法执行以下操作:为每个结果添加几个操作(#t和#f)。

(if (something)
    Do something //true, #t
    Do one thing AND another thing)) //false, #t

作为一个例子,给定一个取整数x的定义过程。如果大于5 - >打印出一条消息。如果小于5 - >打印出消息并将x设置为零:

(if (> x 5)
    "Greater than five"
    "Less than or equal to 5", (= x 0))

重新说明:我正在寻找一种机制,允许我执行以下操作(用Java语法表示):

if (cond) { //true
    //Do this
}
else { //false
    //Do this
    //AND this
}

3 个答案:

答案 0 :(得分:3)

随时随地补上!

好的,所以说你我们真的卡住了,你至少知道if给你两个分支。

(if #t "a" "b") ; => "a"
(if #f "a" "b") ; => "b"

"a""b"可能是什么,对吗?如果他们是程序而该怎么办?

(define (a) "10")
(define (b) "20")
(if #t (a) (b)) ; => "10"
(if #f (a) (b)) ; => "20"

好的,我们知道程序主体可以按顺序评估任意数量的表达式。因此,我们可以将ab扩展为类似

的内容
(define (a) (print "a is ") (print "10") (newline))
(define (b) (print "b is ") (print "20") (newline))
(if #t (a) (b)) ; "a is 10\n"
(if #f (a) (b)) ; "b is 20\n"

好吧所以,每当你想要一个需要评估多个表达式的逻辑分支时,定义一个过程可能有点麻烦,但至少它是有效的。然后,您可以使用lambdas内联程序,以使您的生活更轻松

((if #t
     (λ ()
       (print "a")
       (print "b")
       (newline))
     (λ ()
       (print "c")
       (print "d")
       (newline)))) ; "ab\n"

((if #f
     (λ ()
       (print "a")
       (print "b")
       (newline))
     (λ ()
       (print "c")
       (print "d")
       (newline)))) ; "cd\n"

那么现在你真的不能再说你了。事情可能与他们在Java中看起来完全不同(谢天谢地),但至少事情的表现与预期一致。

当您继续学习语言和常用习语时,您可能偶然发现condbegin。它们可能会让你的生活更轻松,但你必须明白它们并不神奇。您可以自己轻松实现这些。

您可以随时制作所有内容。这是我喜欢计划/球拍的原因之一。没有什么是神圣/神圣的,你基本上可以实现你能想象的任何东西。

答案 1 :(得分:2)

这就是问题,方案中的if与algol家族中的if有很大的不同。 algol衍生物中的If是分支或条件跳转指令; if直接改变代码流。在scheme / lisps中,每个if返回一个值。由于解释器或编译器的内部结构的限制,它不是一个完整的函数是lisps,但是对于大多数目的,你可以将它视为另一个函数。

(if (something)
    Do something //true, #t
    Do one thing AND another thing)) //false, #t

错了,真正发生了什么。

(if condition
  (return value of this first exp) //true value
  (return value or this second exp)) //false value

在方案中,当你想要一个具有副作用的函数时,那就是变异状态你必须非常明确,并且最好用“!”来标记变异状态的函数。在函数名称的末尾。

set! vector-set!之类的程序会返回未指定的值。如果您想要特定序列中的副作用和特定值或多个副作用,则必须使用begin包装整个事件。此外,如果您只是(set! x 0),则只更改本地范围中的x值,这可能不是您想要做的。用于将x传递给函数的任何绑定符号仍然带有它的旧值。(set-car,v ector-set!set-cell-contents!确实修改了跨词法边界调用的数据结构的基础状态)显式递归或隐藏闭包中的值通常是合适的。

begin的语法是(begin exp1 ... expN)Begin依次计算每个表达式,并返回最后一个表达式的值。唯一有用的是如果所有表达式在最后创建副作用之前(变异状态或执行I / O)。另请注意definecond的每个子句都包含且隐式begin

在Java中,打印字符串的过程会产生副作用。如果不是简单地返回一个字符串,那就是(if (> x 5) ..的第一个分支正在做的事情。

为简化起见,我们将字符串打印作为副作用,并将x的下一个或新值作为参数的返回值。

(cond ((> x 5) (display "Greater than five")       (newline) x)
      (else    (display "Less than or equal to 5") (newline) 0))

或几乎相当的

(if  (> x 5) 
     (begin (display "Greater than five")       (newline) x)
     (begin (display "Less than or equal to 5") (newline) 0))

答案 2 :(得分:1)

只需使用begin,这与λ表达式非常相似:

(if #t
    (begin (displayln "Hello, world!") (displayln "wtf"))
    (displayln "stdio.h"))

您可以将任何您喜欢的内容包装到begin表达式中。它们通常用于流控制,因为首先评估begin中的所有内容,但由于if是一个宏(使用define-syntax创建而不是define),它会处理begin作为另一种表达方式。