【问题标题】:"application: not a procedure" while generating prime numbers生成素数时的“应用程序:不是程序”
【发布时间】:2013-02-10 18:29:37
【问题描述】:

我正在尝试输出前 100 个素数并不断收到错误:

应用程序:不是程序; 期望一个可以应用于参数的过程 给定:(#) 参数...:[无]

错误显示在我的 take$ 过程中:

(if (or (= m 0) (null? st))
      '()
      (cons (car st) (take$ (- m 1) ((cdr st)))))))

这是我所有的代码:

(define int-builder$
    (lambda (x)
       (list x (lambda () (int-builder$ (+ 1 x ))))))

(define take$
    (lambda (m st)
       (if (or (= m 0) (null? st))
           '()
           (cons (car st) (take$ (- m 1) ((cdr st)))))))

(define filter-out-mults$
   (lambda (num  st)
     (cond
     (( = (remainder (car st) num) 0) 
         (filter-out-mults$ num ((cadr st))))
         (else 
            (list (car st) (lambda () (filter-out-mults$ num ((cadr st)))))))))

(define sieve$
   (lambda (st)
     (list (car st)
          (lambda() (sieve$ (filter-out-mults$ (car st) ((cadr st))))))))

(define stol$
    (lambda (n) 
      (take$ n (sieve$ (int-builder$ 2)))))

感谢您提供的任何帮助。

【问题讨论】:

  • ((cdr st)) 看起来很可疑
  • 它只是看起来可疑,作者的意图是在 cdr 中调用闭包。看起来可疑的是((cadr st))
  • take$ 过程中显示错误。
  • @AntonKovalenko:不完全是,这些实际上看起来并不那么可疑。查看(list ... (lambda ... )),它对((cadr st)) 应用程序有效。
  • cmets 中的一些 data definitions in comments and corresponding contracts 对您的函数可能有所帮助。我现在正在构建一些(通过手动类型推断)。

标签: scheme primes lazy-sequences sieve non-procedure-application


【解决方案1】:

您的问题是您一直在使用抽象筛的方式不一致。

筛子是这样定义的:

;; A Sieve is a (cons n p), where
;;    n is a Natural Number
;;    p is a Procedure that takes no arguments and returns a Sieve

还是这样定义的

;; A Sieve is a (list n p), where
;;    n is a Natural Number
;;    p is a Procedure that takes no arguments and returns a Sieve

在您的代码中的某些地方,您提取 p 并像这样调用它: ((cdr st));在其他地方,像这样:((cadr st))

您的问题的评论者对每个问题都持怀疑态度的原因是您没有对形成 Sieves 和从 Sieves 提取子部分的规则给出高级定义。像上面这样的数据定义将对此有所帮助。

对我来说,在我添加了数据定义、合约,然后开始单独测试你的功能之后,我很快就发现了问题。 (提示:这与上面提到的((cdr st))((cadr st)) 之间的不一致有关。)

这是我的代码版本。它通过将 Sieve 表示的选择隐藏在抽象接口后面来本地化它;我使用宏来执行此操作,因为流构造函数希望延迟对其接收的表达式的评估(尽管可以通过更改接口来解决此问题,因此 Sieve 构造函数需要采用生成筛子的过程而不是直接表达式) .

读者练习:使用当前的 api,如果有人遵循我在这段代码中给出的数据定义,stream-empty? 永远不会返回 true;你怎么能证明这一点?

;; A Stream is a (list Nat (-> () Stream))
;; but this knowledge should not be used anywhere but in the
;; procedures (and special form) stream-rest, stream-first, stream,
;; and stream-empty?.

;; stream-rest: Stream -> Stream
(define (stream-rest st) ((cadr st)))

;; stream-first: Stream -> Nat
(define (stream-first st) (car st))

;; Special Form: (stream <natural-number> <stream-expr>) is a Stream
(define-syntax stream
  (syntax-rules ()
    ((stream n expr) (list n (lambda () expr)))))

;; Stream -> Boolean
(define (stream-empty? st) (null? st))


;; Nat -> Stream
(define (int-builder$ x)
  (stream x (int-builder$ (+ 1 x))))

;; Nat Stream -> [Listof Nat]
(define (take$ m st)
  (if (or (= m 0) (stream-empty? st))
      '()
      (cons (stream-first st) (take$ (- m 1) (stream-rest st)))))

;; Nat Stream -> Stream
(define (filter-out-mults$ num st)
  (cond
   (( = (remainder (stream-first st) num) 0)
    (filter-out-mults$ num (stream-rest st)))
   (else 
    (stream (stream-first st) (filter-out-mults$ num (stream-rest st))))))

;; Stream -> Stream
(define (sieve$ st)
  (stream (stream-first st)
          (sieve$ (filter-out-mults$ (stream-first st) (stream-rest st)))))

;; Nat -> [Listof Nat]
(define (stol$ n)
  (take$ n (sieve$ (int-builder$ 2))))

【讨论】:

  • 感谢您的解释。我刚刚学习Scheme,它与我习惯的非常不同。谢谢。
猜你喜欢
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2010-12-08
  • 2012-10-28
相关资源
最近更新 更多