如何在Scheme中使用double do循环?

时间:2017-04-07 05:41:34

标签: scheme

  1. 我想用"做"显示(1 1)(1 2)(1 3)(2 1)(2 2)(2 3)(3 1)(3 2)(3 3)的命令 我的代码如下:

    (lambda ( )
    (define a 1)
    (define b 1)
    (do ((a 1 (+ a 1))) (= a 3)
    (do ((b 1 (+ b 1))) (= b 3)
    (display a b)
    )))
    

    但这只会显示3。我做错什么了吗?我该如何纠正?

  2.   

    致Michael Vehrs,

         
        
    1. 非常感谢,它确实有效!但我仍然对退出情况感到困惑。我尝试将代码中的>更改为=,并显示(1 1)(1 2)(2 1)(2 2)。是因为它在a = 3时停止所以它不会打印?

    2.   
    3. 所以"列表"命令可以组合多个变量。但是" newline"命令?我尝试删除它,它只是在最后添加了另一个()

    4.   
    5. 谢谢你的回答。我是一个新的Scheme学习者,试图在TracePro上使用它。你有关于学习计划的任何小费(书,Youtube视频,网站)吗?任何建议都会有所帮助。

    6.   

2 个答案:

答案 0 :(得分:0)

你的意思是:

  (lambda ()
    (do ((a 1 (+ a 1)))
        ((> a 3) (newline))
      (do ((b 1 (+ b 1)))
          ((> b 3))
        (display (list a b))))))

您的代码存在许多问题:do循环的退出条件不正确(并使您的过程返回3)。 display将单个对象和可选端口作为参数。定义变量ab是不必要的,因为do构造无论如何都定义了新的循环变量。

答案 1 :(得分:0)

do循环只是递归函数的语法糖。你也可以习惯直接写它。这是一种使用一个带有两个变量和一个累加器的名为let的方法。

(let loop ((a 3) (b 3) (acc '()))
  (cond ((zero? a) acc)                                  ; finished
        ((zero? b) (loop (sub1 a) 3  acc))               ; b finsihed, reduce a and reset b
        (else (loop a (sub1 b) (cons (list a b) acc))))) ; reduce b and add to front of acc
; ==> ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))

请注意,这会以相反的顺序生成结果,因此对于始终以相反顺序创建的列表来说它是最佳的,因为它只能在前面添加新元素。