Reputation: 688
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
<+>
is compose<Y>
is create a function that applies a list of functions to one arg</>
is partially apply<?>
is choiceUpvotes: 2
Views: 254
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