Scheme void error?

时间:2013-12-07 10:10:24

标签: scheme racket

我是计划新手,我写了一个小程序,根据开始和结束索引从列表中获取原子。

(define counter 0)
(define (sub x y a_list) 
  (cond
    ((null? a_list) '())
    ((and (>= counter x) (< counter y)) (cons x (sub x y (cdr a_list))))
    (else((set! counter (+ counter 1)) (sub x y (cdr a_list))))
  ))

我没有看到这个代码有任何问题,但是当我执行它时,例如:

(sub 1 3 '(X G H S E))

我收到以下错误:

function call: expected a function after the open parenthesis, but received (void)

2 个答案:

答案 0 :(得分:3)

我建议如下:

(define (sub x y lst)
  (let loop ((lst lst) (counter 0))
    (cond
      ((null? lst) 
       '())
      ((and (>= counter x) (< counter y)) 
       (cons (car lst) (loop (cdr lst) (+ 1 counter))))
      (else 
       (loop (cdr lst) (+ 1 counter))))))
  • 没有全局变量,counter是本地的
  • 你是x,但你必须(汽车)

你的代码,重写,将是

(define counter 0)

(define (sub x y a_list) 
  (cond
    ((null? a_list) 
     '())
    ((and (>= counter x) (< counter y)) 
     (begin
       (set! counter (+ counter 1)) 
       (cons (car a_list) (sub x y (cdr a_list)))))
    (else
     (begin
       (set! counter (+ counter 1)) 
       (sub x y (cdr a_list))))))

但第二次执行失败,因为计数器未重置为0:

(sub 1 3 '(X G H S E))
=> '(G H)
(sub 1 3 '(X G H S E))
=> '()

关于你的初步问题:

  1. 在只允许使用一种表单的地方对表单进行分组(if可以考虑),使用begin(有关详细信息,请参阅优秀的Racket帮助)

  2. ((f x ...) y ...)首先评估(f x ...),它应该返回一个程序p;然后它评估(p y ...)。在您的情况下,fset!,总是评估为(void),因此评估为((void) y ...)。因此错误信息。

  3. 编辑

    在没有计数器的情况下说明@ WorBlux的想法:

    (define (sub x y lst)
      (cond
        ((or (null? lst) (<= y 0))
         '())
        ((> x 0)
         (sub (- x 1) (- y 1) (cdr lst)))
        (else
         (cons (car lst) (sub (- x 1) (- y 1) (cdr lst))))))
    

答案 1 :(得分:1)

在这个问题上你实际上并不需要一个计数器只是想一下递归的模式

(sub xy L)等于(sub(?x)(?y)(cdr L))其中x大于零,相当于(?(?L)(sub x(?y) (cdr L)))其中x为0但y为正且相当于空列表,其中y小于零。