1

I am new to scheme and i have wrote a small program that takes atoms from list based on start and end indices.

(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))))
  ))

I don't see any problem with this code but when i execute it for example:

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

I get the following error:

function call: expected a function after the open parenthesis, but received (void)
ykh
  • 1,775
  • 3
  • 31
  • 57
  • Double parenthesis around your `set!`, but the result is wrong. – uselpa Dec 07 '13 at 10:11
  • it should be double parenthesis, cause otherwise i can't put tow statements inside else. – ykh Dec 07 '13 at 10:12
  • can you please re-write the else statement because i have tired many things with the parenthesis before and non worked for me – ykh Dec 07 '13 at 10:15
  • possible duplicate of ["application: not a procedure" in binary arithmetic procedures](http://stackoverflow.com/questions/19022704/application-not-a-procedure-in-binary-arithmetic-procedures) – Joshua Taylor Dec 07 '13 at 14:15

2 Answers2

3

I would suggest the following:

(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))))))
  • no global variable, counter is local here
  • you cons x, but you must cons (car lst)

Your code, rewritten, would be

(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))))))

but the second execution would fail because the counter is not reset to 0:

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

Regarding your initial question:

  1. to group forms in a place where only one form is allowed (if comes to mind), use begin (see the excellent Racket help for details)

  2. ((f x ...) y ...) first evaluates (f x ...), which should return a procedure p; then it evaluates (p y ...). In your case, f was set!, which always evaluates to (void), so this was evaluated as ((void) y ...). Hence the error message.

EDIT

Illustrating @WorBlux's idea without a counter:

(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))))))
uselpa
  • 18,732
  • 2
  • 34
  • 52
  • I have tired your re-written code but still produce the same erorr, i am using dr.racet advance student so i don't know if that is the problem. i had to wrap the set with another parenthesis because it wouldn't compile otherwise. – ykh Dec 07 '13 at 10:28
  • Ok, modified. You *really* should state in your question what language you use. – uselpa Dec 07 '13 at 10:36
1

You don't actually need a counter in this problem just think about the patteren of recursion a little more

(sub x y L) is equivalent to (sub (? x) (? y) (cdr L)) where x is greater than zero, and is equivalent to (? (? L) (sub x (? y) (cdr L))) where x is 0 but y is positive and equivalent to the empty list where y is less than zero.

WorBlux
  • 1,423
  • 11
  • 20