无法理解Guile Scheme Code

时间:2016-06-24 10:07:16

标签: scheme pascals-triangle mit-scheme guile

我正在尝试使用Guile Scheme在终端上打印Pascal的三角形 What is Pascal's Triangle?

这是脚本:

 #!/usr/local/bin/guile \
-e main -s 
!#
(define (fact-iter product counter max-count)
    (if (> counter max-count)
         product
         (fact-iter (* counter product) (+ counter 1) max-count)))

(define (factorial n)
    (fact-iter 1 1 n))

(define (n-C-r n r) 
    (/ (factorial n) (* (factorial (- n r)) (factorial r))
    )
)


(define (row-iter r l n)
    (cond   ((= r 0) ((display 1) (row-iter (+ r 1) l n)))
            ((and (> r 0) (< r l)) ((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))
            ((= r l) (display 1))
    )
)


(define (line-iter l n)
    (cond ((<= l n) ( (row-iter 0 l n)
                        (line-iter (+ l 1) n) ) )
    )
)

(define (pascal-triangle n)
    (line-iter 0 n) )

(define (main args)
    (pascal-triangle (string->number (car (cdr args)) 10))
    )

文件名是pascalTriangle.scm
顶部的 Shebang符号具有正确的guile路径 我通过 chmod + x pascalTriangle.scm
给予了权限 使用 ./ pascalTriangle.scm 5

命令运行程序

运行时,上面的脚本会出现以下输出/错误:

  

1Backtrace:在ice-9 / boot-9.scm中:
  157:5 [catch #t#&lt; catch-closure ac8400&gt; ...]
  在未知档案中:
  ?:4 [apply-smob / 1#&lt; catch-closure ac8400&gt;]
  在ice-9 / boot-9.scm中:
  63:3 [call-with-prompt prompt0 ...]
  在ice-9 / eval.scm中:
  432:2 [eval ##]
  在/home/tarunmaganti/./pascalTriangle.scm中:
  27:1 [line-iter 0 4]
  在未知档案中:
  ?:0 [#&lt;未指定&gt; #&lt; unspecified&gt;]

     

错误:在程序#&lt;未指定&gt;:
  错误:要应用的类型错误:#&lt; unspecified&gt;

请注意,输出的第一个字符是1,这意味着代码执行到程序的第一部分 row-iter 即(显示1)并且之后可能会出现错误。

但输出显示错误在程序 line-iter 中。我不明白。
如果程序中的任何错误被指出并更正以使其打印Pascal的三角形,我将不胜感激。

Edit1:我编辑了错误/输出文本,我替换了'&lt;'和'&gt;'与HTML实体。角括号内的文字以前是不可见的。

2 个答案:

答案 0 :(得分:1)

问题是你在cond中的后果表达式周围添加了多余的括号。由于cond明确begin,因此您的代码今天看起来像这样:

(define (row-iter r l n)
  (cond ((= r 0)
         ;; you see the double (( ?
         ((display 1)
          (row-iter (+ r 1) l n)))

        ((and (> r 0) (< r l))
         ;; you see the double (( ?
         ((display (n-C-r l r))
          (display " ")
          (row-iter (+ r 1) l n)))

        ((= r l)
         ;; without double (( and thus ok
         (display 1))))

需要删除多余的括号,如下所示:

(define (row-iter r l n)
  (cond ((= r 0)
         (display 1)
         (row-iter (+ r 1) l n))

        ((and (> r 0) (< r l))
         (display (n-C-r l r))
         (display " ")
         (row-iter (+ r 1) l n))

        ((= r l)
         (display 1))))

如果您使用if,则必须使用begin

(define (row-iter r l n)
  (if (= r 0)
      (begin
        (display 1)
        (row-iter (+ r 1) l n))
      (if (and (> r 0) (< r l))
          (begin
            (display (n-C-r l r))
            (display " ")
            (row-iter (+ r 1) l n))          
          (display 1))))

修复此过程不会解决您的问题,因为您在line-iter中也有相同的错误。您可能会在每个((字词的开头看到双cond,但除非您正在做一些奇特的事情,否则您不应该在其他任何地方期待它。

当添加多余的括号((display "something") #t)时,它被解释为(display "something")将返回一个过程,并且您想要检查具有参数#t的该过程的结果将变为什么。当评估所有部件时,它失败,因为它发现未定义的值不是过程。有些情况下有效:

((if (< x 0) - +) x 1) ; absolute increment value without changing sign

在这里,当-小于零时,您会看到第一部分被评估为评估x的结果。如果它是-10,则结果为-11,如果是10,则应用的过程将是对+的评估,结果为11

稍后它会发现值3不是一个程序,你就会发现错误。并得到结果Scheme应该做(应用3&#39;(#t))and it detects that 3 (in your case what desiplay returns which is an unspecified value) Scheme interprets this by evaluating(显示(nCr lr)`打印一些东西和返回值,由规范由于括号过多,我未定义并因此自由选择实施者,然后作为程序应用。

在Guile中,规范中未定义的值的结果变为显示#<unspecified>的单例,并且被REPL忽略。您可能会发现一个Scheme实现,其中未指定的值是一个不带参数的过程,其中您的实现将完美地工作但不可移植。

答案 1 :(得分:0)

Sylwester在答案中陈述的错误是((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))表达式。该语句确实通过评估((display (n-C-r l r))来解释这一点,((display (n-C-r l r))打印一些东西并返回未定义的值,并作为一个程序应用,将(begin <e1> <e2> <e3>....<en>)视为过分括号。

我使用Sequencing解决了这个问题。 开始特殊表单用于组合多个语句并返回最后一个语句的值。 Sequencing in MIT-Scheme。这也适用于guile计划。

开始特殊形式的语法:<en>
 它返回(define (row-iter n r) (cond ((= r 0) (begin (display 1) (display " ") (row-iter n (+ r 1)))) ((and (> r 0) (< r n)) (begin (display (n-C-r n r)) (display " ") (row-iter n (+ r 1)))) ((= r n) (display 1)) ) ) 表达式的返回值。

以下是更改后的代码:

./pascalTriangle 5

虽然输出没有正确格式化为“三角形”,但我们可以在更改代码后得到左缩进的pascal三角形。

通过运行 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 ,我们将输出视为

break