podcherkLIfe
podcherkLIfe

Reputation: 192

Small question about scheme

I'm very new to lisp and recently i discovered the thin that I don't understand.

This code works:

(define (f x) (define a x) (define (b) a) (b))

And this doesn't:

(define (f x) (define a x) (define b a) b)

Why?

Upvotes: 4

Views: 166

Answers (3)

newacct
newacct

Reputation: 122439

You might be seeing the change in behavior between the R5RS and R6RS standards. One of the changes in R6RS is "Internal definitions are now defined in terms of letrec*."

In R5RS, the internal defines are completely equivalent to a letrec. In particular, the section on internal definitions says that "Just as for the equivalent letrec expression, it must be possible to evaluate each <expression> of every internal definition in a <body> without assigning or referring to the value of any <variable> being defined."

However, in R6RS, internal defines are equivalent to a letrec*. And, as you would expect, letrec* allows you to refer to the value of preceding variables in the intializer for later variables.

Upvotes: 0

jcubic
jcubic

Reputation: 66490

In kawa interpeter it works In Guile it doesn't, because this code

(define (f x) (define a x) (define b a) b)

is expand to

(define (f x) (letrec ((a x) (b a)) b))

And you can't access to a before I's assign. letrec won't work for non-function definitions, for example:

(letrec ((x 5)
         (y x))
     y)

You can use let* insted

(define (f x) (let* ((a x) (b a)) b))

In this code

(define (f x) (define a x) (define (b) a) (b))

In procedure b you access a varible when it's already defined.

Upvotes: 2

Eli Barzilay
Eli Barzilay

Reputation: 29546

You should look up discussions about letrec* -- some implementations use it as a more permissive version of the stricter letrec, which results in the difference you see.

Upvotes: 2

Related Questions