It doesn't matter for the end result since x and y are bound in the lexical scope to 2 and 3. You are saying you don't want:
(let ((x 2) (y 3))
(let ((foo (some-other-function z y)))
(if (= x foo) T)))
But you want:
(let ((foo (some-other-function z 3)))
(if (= 2 foo) T))
But I can't tell the difference. Can you?
Anyway. You can coerce any data structure to be a function like this:
(defun create-lambda (x y)
(coerce `(lambda(z)
(let ((foo (some-other-function z ,y)))
(when (= ,x foo) T)))
'function))
Or you can make create-lambda a macro:
(defmacro create-lambda (x y)
`(lambda(z)
(let ((foo (some-other-function z ,y)))
(when (= ,x foo) T))))
The differences between these are easy to spot if you call it with side effects(create-lambda (print 3) (print 4)). In the first the side effects will happen right away since functions evaluate all their arguments while the macro will just replace the whole thing for x and y and the side effect happen at call time.
#<FUNCTION :LAMBDA (Z) (LET ((FOO (SOME-OTHER-FUNCTION Z Y))) (IF (= X FOO) T))>is not standardized. In this case, since the value ofxandycan't be changed (unless they've been globally declared special), there should be no observable difference.