jgon
jgon

Reputation: 688

Force racket to accept recursive variable definition as a recursive function definition

For fun I've created a bunch of functions in Racket that create and combine other functions.

Now I've defined a recursive function in terms of them:

(define (my-flatten2 struct)
  ((<?> pair?
       (<+> append <m>
            (</> map my-flatten2)
            (<Y> car cdr))
       list)
   struct))

I tried this first, but it didn't work (it gave me a can't reference identifier before its definition error):

(define my-flatten-error
  (<?> pair?
       (<+> append <m>
            (</> map my-flatten-error)
            (<Y> car cdr))
       list))

Can anyone explain why it didn't work, and whether or not there is a way to fix it.

For the record

Upvotes: 2

Views: 254

Answers (1)

John Clements
John Clements

Reputation: 17203

Racket is an eager language; it evaluates arguments before passing them. So, your code does not work for the same reason that

(define p (add1 p))

doesn't work.

In this case, assuming that my-flatten error does turn out to be a function, it might be fairly easy to solve your problem just by delaying the evaluation of my-flatten-error:

(define my-flatten-error
  (<?> pair?
       (<+> append <m>
            (</> map (lambda args 
                       (apply my-flatten-error args)))
            (<Y> car cdr))
       list))

You can also hide the lambda using a macro:

(define-syntax delay-fn
  (syntax-rules ()
    [(delay-fn f) (lambda args (apply f args))]))


(define my-flatten-error
  (<?> pair?
       (<+> append <m>
            (</> map (delay-fn my-flatten-error))
            (<Y> car cdr))
       list))

... if you find that visually more pleasing.

Upvotes: 3

Related Questions