MiniKanren and function application: use project to apply a logic-derived lambda value

I’ve been scratching my head over how to apply a function arrived at dynamically via logical constraint in MiniKanren. Consider this:

(define assoco (lambda (n l r) ...) ;; (assoc 'b '((a 1) (b 2) (c 3)) => 2
(define applyo
(lambda (env out)
(fresh (looked-up-fn)
(assoco '*torun env looked-up-fn)
(looked-up-fn env out)
)
)
)

but it fails at runtime with a pretty cryptic error:

In unknown file:
?: 0 [#(apply-fun) #(ready-to-run-env) #(q)]
ERROR: In procedure #(apply-fun):
ERROR: Wrong type to apply: #(apply-fun)

So it wasn’t obvious what was going on for a while until I realized that what it’s telling me is that some kind of macro expansion is happening. I kind of knew that, but didn’t realize what it meant to application. The description of the “project” function in MiniKanren hadn’t been clear to me, nor had the necessity of extracting the bound definition of the function.

It wasn’t obvious from the docs I read that this was needed and I didn’t see much relevant advice out there, but it *is* needed here:

(define applyo
(lambda (env out)
(fresh (looked-up-fn)
(assoco '*torun env looked-up-fn)
(project (looked-up-fn)
(looked-up-fn env out)
)
)
)
)

It’d be cool if there was some way to have the macro fail early with a warning that it’s about to expand logic variable that doesn’t cleanly work as a scheme value, but now I know, and so does anyone else who constrains the google relation with the appropriate terms :-)

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.