3

I'm trying to write a scheme func that behaves in a way similar to a loop.

(loop min max func)

This loop should perform the func between the range min and max (integers)

-- one of an example like this

(loop 3 6 (lambda (x) (display (* x x)) (newline)))

9
16
25
36

and I define the function as

( define ( loop min max fn)
    (cond
        ((>= max min) ( ( fn min ) ( loop (+ min 1 ) max fn)  ) )
    )
)

when I run the code I get the result then an error occur. I couldn't handle this error.

(loop 3 6 (lambda (x) (display(* x x))(newline)))

9
16
25
36

Backtrace:
In standard input:
  41:  0* [loop 3 6 #<procedure #f (x)>]

In utku1.scheme:
   9:  1  (cond ((>= max min) ((fn min) (loop # max fn))))
  10:  2  [#<unspecified> ...
  10:  3*  [loop 4 6 #<procedure #f (x)>]
   9:  4   (cond ((>= max min) ((fn min) (loop # max fn))))
  10:  5   [#<unspecified> ...
  10:  6*   [loop 5 6 #<procedure #f (x)>]
   9:  7    (cond ((>= max min) ((fn min) (loop # max fn))))
  10:  8    [#<unspecified> ...
  10:  9*    [loop 6 6 #<procedure #f (x)>]
   9: 10     (cond ((>= max min) ((fn min) (loop # max fn))))
  10: 11     [#<unspecified> #<unspecified>]

**utku1.scheme:10:31: In expression `((fn min) (loop # max ...))`:
    utku1.scheme:10:31:Wrong type to apply: `#<unspecified>`
ABORT: (misc-error)**
clstrfsck
  • 14,715
  • 4
  • 44
  • 59
tkcn
  • 516
  • 3
  • 10
  • 29

2 Answers2

5

Each clause of a cond expression has the form (cond expr1 expr2...), but you've wrapped both expr1 and expr2 in parens when they should be separate. The solution would be to either specify begin at the beginning: ((>= max min) (begin expr1 expr2)) or make the begin implicit: ((>= max min) expr1 expr2).

Alternatively, it might make more sense to use a when statement instead of a cond, since you only have one choice:

(define (loop min max fn)
  (when (>= max min)
    (fn min)
    (loop (+ min 1) max fn)))

Because both cond and when are macros that use if, both versions become

(define (loop min max fn)
  (if (>= max min)
    (begin (fn min) (loop (+ min 1) max fn))
    (void)))

anyways.

erjiang
  • 44,417
  • 10
  • 64
  • 100
2
( ( fn min ) ( loop (+ min 1 ) max fn) )

This is the problem. What you want this to do is to execute (fn min) and then (loop (+ min 1 ) max fn) afterwards. What it actually does do is, it executes (fn min), then (loop (+ min 1 ) max fn) and then it tries to apply the result of (fn min) to the result of (loop (+ min 1 ) max fn). Since the result of (fn min) is not a function, this is an error.

To get what you want, do ( begin (fn min) (loop (+ min 1) max fn) ). begin allows you to execute multiple expressions after one another.

sepp2k
  • 363,768
  • 54
  • 674
  • 675