Reputation: 10107
I have the following code:
(define (get-data)
(define port (open-input-file "../data/problem11.txt"))
(define field 0)
(define (get-fields)
(define field (read port))
(cond ((not (eof-object? field))
(cons field (get-fields)))
(else '())))
(define returned (get-fields))
(close-input-port port)
returned)
(get-data)
I can't find any problem with my code according to the manuals, and nothing comes up on google when searched, but when I run the code, SCM (my chosen scheme interpreter) gives me the following error:
;ERROR: "/usr/lib/scm/Iedline.scm": unbound variable: get-fields
; in expression: (get-fields)
; in scope:
; (returned get-fields field port . #@define)
; () procedure get-data
;STACK TRACE
1; (#@define ((returned (get-fields)) (get-fields (#@lambda () (# ...
2; (#@get-data)
But when I make my code look like this, it works fine:
(define (get-data port)
(define field 0)
(define (get-fields)
(define field (read port))
(cond ((not (eof-object? field))
(cons field (get-fields)))
(else '())))
(get-fields))
(define port (open-input-file "../data/problem11.txt"))
(define alfa (get-data port))
(close-input-port port)
Why is it that when I attempt to define returned as the returned list of get-fields that I get an unbound variable error, but when I define alfa as the returned list of get-data (in the second code block), it works okay? Is it that get-fields is recursive? I don't get it. Any answers here would be awesome, thanks.
Upvotes: 3
Views: 202
Reputation: 223183
Implementations are allowed to implement internal define
s using one of two possible semantics: letrec
and letrec*
.
SCM has obviously chosen to use letrec
semantics. That means that, given a bunch of internal define
s, none of them can immediately refer to the value of another internal define
in that same bunch: the same restriction that applies to letrec
.
Some implementations, like Racket, use letrec*
semantics. That means that any variable defined in an earlier internal define
can be used directly by later internal define
s. (In other words, your code will work fine in any letrec*
-based implementation.)
Since you're using a letrec
-based implementation, do this:
(let ((returned (get-fields)))
(close-input-port port)
returned)
Upvotes: 6