0

我正在尝试使用 Guile 方案在终端上打印帕斯卡三角形。
什么是帕斯卡三角?

这是脚本:

 #!/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 #<catch-closure ac8400> ...]
在未知文件中:
     ?:4 [apply-smob/1 #<catch-closure ac8400 >]
在 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 [#<unspecified> #<unspecified>]

错误:在过程 #<unspecified>:
错误:要应用的类型错误:#<unspecified>

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

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

Edit1:我编辑了错误/输出文本,我用 HTML 实体替换了 '<' 和 '>'。尖括号内的文字以前是不可见的。

4

2 回答 2

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应该做的结果 (apply 3 '(#t)) and it detects that 3 (in your case whatdesiplay returns which is an unspecified value) Scheme interprets this by evaluating(display (nCr lr)` 打印一些东西和返回的值,由规范我未定义,因此实现者的自由选择,然后应用作为一个过程,因为多余的括号。

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

于 2016-06-24T10:28:54.110 回答
0

Sylwester 在他的回答中所说的错误在于((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))表达。该语句确实通过评估((display (n-C-r l r))which 打印某些内容并返回未定义的值来解释这一点,并将其用作考虑((display (n-C-r l r))过度括号的过程。

我使用测序解决了这个问题。begin特殊形式用于组合多条语句并返回最后一条语句的值 。MIT-Scheme 中的测序。这也适用于诡计。

begin特殊形式的语法:(begin <e1> <e2> <e3>....<en>)
返回表达式的返回值<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,我们得到的输出为

1    
1 1    
1 2 1    
1 3 3 1    
1 4 6 4 1    
1 5 10 10 5 1
于 2016-06-24T17:18:39.393 回答