In emacs lisp (but answers relating to common lisp are also welcome) I have a library that uses a macro and I want to hijack one of the macro's arguments only when executed in a certain context. Essentially what I want is a macro:
; My macro. This is a sketch of what I want that doesn't work.
(defmacro hijack-f (body)
`(macrolet ((f (x) `(f (+ 1 ,x))))
,#body))
; Defined in the library, I don't want to deal with these
(defmacro f (x) x)
(defun g (x) (f x))
So that
(g 1) ; => 1
(hijack-f (g 1)) ; => 2
(hijack-f (hijack-f (g 1))) ; => 3
EDIT: #melpomene and #reiner-joswig correctly point out that f is expanded in g before hijack-f. As a followup is there a hijack-f such that:
(f 1) ; => 1
(hijack-f (f 1)) ; => 2
(hijack-f (hijack-f (f 1))) ; => 3
As far as I know, what you want is not possible because g does not contain an invocation of f. Instead f runs first and expands to (part of) the definition of g.
That is:
(defun g (x) (f x))
immediately turns into
(defun g (x) x)
Which then defines g as a function (whose value is (lambda (x) x)).
Messing with f at runtime doesn't affect anything because its invocation is long gone by the time you call g.
If you are happy for your f to be a function and not a macro, and to use CL not elisp, then you are after flet and a macro like this:
(defmacro hijack-f (&body body)
`(flet ((f (x)
(f (1+ x))))
,#body))
Given a global defintion of f:
(defun f (x)
x)
Then
> (hijack-f (f 1))
2
> (hijack-f (hijack-f (f 1)))
3
And so on.
(As others have pointed out, you can't hijack code that has already been compiled with a macro like this: you would need to do it by having f cooperate in the hijacking.)
Related
In the following code how can i have the x and y variables to reflect the expressions given at macro call time?
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
#'(lambda (w h) (list x y)))))
When expanding a call like:
(defrule (70 (* 1/2 w) (+ h 3)))
it returns:
(DESTRUCTURING-BIND (P X Y) '(70 (* 1/2 W) (+ H 3))
#'(LAMBDA (W H) (LIST X Y)))
where the original expressions with W and H references are lost. I tried back-quoting the lambda function creation:
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
`#'(lambda (w h) (list ,x ,y)))))
But a same call:
(defrule (70 (* 1/2 w) (+ h 3)))
expands to:
(DESTRUCTURING-BIND
(P X Y)
'(70 (* 1/2 W) (+ H 3))
`#'(LAMBDA (W H) (LIST ,X ,Y)))
which returns a CONS:
#'(LAMBDA (W H) (LIST (* 1/2 W) (+ H 3)))
which can not be used by funcall and passed around like a function object easily. How can i return a function object with expressions i pass in as arguments for the x y part of the init-form with possible W H references being visible by the closure function?
You're getting a cons because you have the backquotes nested.
You don't need backquote around destructuring-bind, because you're destructuring at macro expansion time, and you can do the destructuring directly in the macro lambda list.
(defmacro defrule ((p x y) &rest replication-patterns)
(let (rule-table)
`#'(lambda (w h) (list ,x ,y))))
Looking at your code:
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
#'(lambda (w h) (list x y)))))
You want a macro, which expands into code, which then at runtime takes code and returns a closure?
That's probably not a good idea.
Keep in mind: it's the macro, which should manipulate code at macro-expansion time. At runtime, the code should be fixed. See Barmar's explanation how to improve your code.
my elisp program is:
(defun test (f x) (f x))
(test (lambda (x) (* x x)) 10)
run it, an error happened:
* Eval error * Symbol's function definition is void: f
Emacs is a lisp-2, so has a different namespace for functions and variables. So, in test, the f in the second (f x) is not the same as the (f) in the parameter list.
Try
(defun test (f x) (funcall f x))
All is good.
Here's the correction:
(defun test (f x)
(funcall f x))
(test (lambda (x) (* x x)) 10)
I started learning Common Lisp recently, and (just for fun) decided to rename the lambda macro.
My attempt was this:
> (defmacro λ (args &body body) `(lambda ,args ,#body))
It seems to expand correctly when by itself:
> (macroexpand-1 '(λ (x) (* x x)))
(LAMBDA (X) (* X X))
But when it's nested inside an expression, execution fails:
> ((λ (x) (* x x)) 2)
(Λ (X) (* X X)) is not a function name; try using a symbol instead
I am probably missing something obvious about macro expansion, but couldn't find out what it is.
Maybe you can help me out?
edit:
It does work with lambda:
> ((lambda (x) (* x x)) 2)
4
edit 2:
One way to make it work (as suggested by Rainer):
> (set-macro-character #\λ (lambda (stream char) (quote lambda)))
(tested in Clozure CL)
In Common Lisp LAMBDA is two different things: a macro and a symbol which can be used in a LAMBDA expression.
The LAMBDA expression:
(function (lambda (x) (foo x)))
shorter written as
#'(lambda (x) (foo x))
An applied lambda expression is also valid:
((lambda (x) (+ x x)) 4)
Above both forms are part of the core syntax of Common Lisp.
Late in the definition of Common Lisp a macro called LAMBDA has been added. Confusingly enough, but with good intentions. ;-) It is documented as Macro LAMBDA.
(lambda (x) (+ x x))
expands into
(function (lambda (x) (+ x x))
It makes Common Lisp code look slightly more like Scheme code and then it is not necessary to write
(mapcar #'(lambda (x) (+ x x)) some-list)
With the LAMBDA macro we can write
(mapcar (lambda (x) (+ x x)) some-list)
Your example fails because
((my-lambda (x) (* x x)) 2)
is not valid Common Lisp syntax.
Common Lisp expects either
a data object
a variable
a function call in the form (function args...)
a function call in the form ((lambda (arglist ...) body) args...)
a macro form like (macro-name forms...)
a special form using one of the built-in special operators like FUNCTION, LET, ...
defined in the list of special operators in Common Lisp
As you can see a syntax of
((macro-name forms...) forms...)
is not a part of Common Lisp.
It is possible to read the character λ as LAMBDA:
(defun λ-reader (stream char)
(declare (ignore char stream))
'LAMBDA)
(set-macro-character #\λ #'λ-reader)
Example:
CL-USER 1 > ((λ (x) (* x x)) 3)
9
CL-USER 2 > '(λ (x) (* x x))
(LAMBDA (X) (* X X))
You might also think of LAMBDA as an operator which, given a term and a list of free variables, returns a function. This p.o.v. takes LAMBDA out of the family of basic functions and elementary macros -- at least as far as the interpreter is concerned.
(defun lambda-char (stream char)
"A lambda with only ONE arg _"
(declare (ignore char))
(let ((codes (read stream nil)))
`(lambda (_) ,codes)))
(set-macro-character #\λ #'lambda-char t)
λ(+ 1 2 _) ; => (lambda (_) (+ 1 2 _))
Maybe this is more concise, with ONLY ONE arg of _
I learned quite a bit of scheme from SICP but am more interested in common lisp now. I know common lisp's fold is reduce, with special arguments for left or right folding, but what is the equivalent of unfold? Googling has not helped much. In fact I get the impression there is no unfold???
Common Lisp has (loop ... collect ...). Compare
(loop for x from 1 to 10 collect (* x x))
with its equivalence using unfold:
(unfold (lambda (x) (> x 10))
(lambda (x) (* x x))
(lambda (x) (+ x 1))
1)
In general, (unfold p f g seed) is basically
(loop for x = seed then (g x) until (p x) collect (f x))
Edit: fix typo
The common lisp hyperspec doesn't define an unfold function, but you can certainly write your own. Its scheme definition translates almost symbol for symbol.
I have the following code
(defun avg-damp(f)
#'(lambda(x) (/ (+ (funcall f x) x) 2.0)))
A call
(funcall (avg-damp #'(lambda(v) (* v v))) 10)
returns 55.0 (the correct value) in SBCL but crashes with the following stack in emacs lisp
Debugger entered--Lisp error: (void-variable f)
(funcall f x)
(+ (funcall f x) x)
(/ (+ (funcall f x) x) 2.0)
(lambda (x) (/ (+ ... x) 2.0))(10)
funcall((lambda (x) (/ (+ ... x) 2.0)) 10)
eval((funcall (avg-damp (function ...)) 10))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
How can I make it work in Emacs lisp?
This style of programming does not work in plain Emacs Lisp. Emacs Lisp uses dynamic binding and languages like Scheme and Common Lisp are using lexical binding. Your code exposes the difference. See: Extent in Emacs Lisp
See also this question: How do I do closures in Emacs Lisp? and the 'solution' with lexical-let. lexical-let is an extension for Emacs Lisp in the "cl" package.
See also: since Emacs 24.1 there is optional lexical binding. Learn how to use it: using lexical binding.
A tricky question, but finally got this figured out. The problem is that #' in the definition of avg-damp makes the compiler compile the lambda function at the time when avg-damp itself is compiled, before the actual value of f is known. You need to delay the compilation of this function to a later point in time, when avg-damp is called, like this:
(defun avg-damp (f)
`(lambda(x) (/ (+ (funcall ,f x) x) 2.0)))
(funcall (avg-damp #'(lambda(v) (* v v))) 10)
Backquoting does the trick.
Edit: Of course, the whole problem goes away if you define avg-damp in an uncurried form, such as this:
(defun avg-damp (f x)
(/ (+ (funcall f x) x) 2.0))
(funcall 'avg-damp #'(lambda(v) (* v v)) 10)
But I guess you have your reasons not to do so.