elisp functions as parameters and as return value - lisp

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.

Related

Defining a let macro scope in emacs lisp

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.)

define-modify-macro with operator argument

In Section 12.4 of On Lisp, Paul Graham writes, "Unfortunately, we can't define a correct _f with define-modify-macro, because the operator to be applied to the generalized variable is given as an argument."
But what's wrong with something like this?
(define-modify-macro _f (op operand)
(lambda (x op operand)
(funcall op x operand)))
(let ((lst '(1 2 3)))
(_f (second lst) #'* 6)
lst)
=> (1 12 3)
Has there perhaps been a change made to define-modify-macro in ANSI Common Lisp that wasn't valid at the time On Lisp was written? Or are there reasons other than the one stated for not using define-modify-macro here?
It appears that Graham want's to be able to make a call such as
(_f * (second lst) 6)
rather than
(_f #'* (second lst) 6)
But surely that's not in keeping with a Lisp2 such as Common Lisp?
According to both Lispworks's Hyperspec and CLtL2 (look for define-modify-macro), the function is assumed to be a symbol (to a function or a macro). As far as I know, the following definition might not be conforming the specification:
(define-modify-macro _f (op operand)
(lambda (x op operand)
(funcall op x operand)))
But of course, it is possible that an implementation allows it.
To be sure you are conforming to the standard, you can define your own function, or even a macro:
(defmacro funcall-1 (val fun &rest args)
`(funcall ,fun ,val ,#args))
(define-modify-macro _ff (&rest args) funcall-1)
(let ((x (list 1 2 3 4)))
(_ff (third x) #'+ 10)
x)
If you wanted to have the function as a second argument, you could define another macro:
(defmacro ff (fun-form place &rest args)
`(_ff ,place ,fun-form ,#args))
Basically, your approach consists in wrapping funcall in define-modify-macro, and give the desired function as an argument of that function. At first sight, it looks like a hack, but as we can see below, this gives the same macroexanded code as the one in On Lisp, assuming we modify the latter a little.
The macroexpansion of the above is:
(LET ((X (LIST 1 2 3 4)))
(LET* ((#:G1164 X) (#:G1165 (FUNCALL #'+ (THIRD #:G1164) 10)))
(SB-KERNEL:%RPLACA (CDDR #:G1164) #:G1165))
X)
The version in On Lisp behaves as follows:
(defmacro _f (op place &rest args)
(multiple-value-bind (vars forms var set access)
(get-setf-expansion
place)
`(let* (,#(mapcar #'list vars forms)
(, (car var) (,op ,access ,#args)))
,set)))
(let ((x (list 1 2 3 4)))
(_f * (third x) 10)
x)
Macroexpansion:
(LET ((X (LIST 1 2 3 4)))
(LET* ((#:G1174 X) (#:G1175 (* (THIRD #:G1174) 10)))
(SB-KERNEL:%RPLACA (CDDR #:G1174) #:G1175))
X)
Here, the * is injected directly by the macroexpansion, which means that the resulting code has no possible runtime overhead (though compilers would probably handle your (funcall #'+ ...) equally well). If you pass #'+ to the macro, it fails to macroexpand. This is the major difference with your approach, but not a big limitation. In order to allow the On Lisp version to accept #'*, or even (create-closure) as an operator, it should be modified as follows:
(defmacro _f (op place &rest args)
(multiple-value-bind (vars forms var set access)
(get-setf-expansion
place)
`(let* (,#(mapcar #'list vars forms)
(, (car var) (funcall ,op ,access ,#args)))
,set)))
(see the call to funcall)
The previous example is then expanded as follows, for #'*:
(LET ((X (LIST 1 2 3 4)))
(LET* ((#:G1180 X) (#:G1181 (FUNCALL #'* (THIRD #:G1180) 10)))
(SB-KERNEL:%RPLACA (CDDR #:G1180) #:G1181))
X)
Now, it is exactly as your version. On Lisp uses _f to demonstrate how to use get-setf-expansion, and _f is a good example for that. But on the other hand, your implementation seems equally good.
On the question of whether one might prefer to pass * or #'*, we can also note that the define-modify-macro version of _f and #coredump's adapted version (with funcall) both accept lambda forms in the op position with or without #' e.g. both (lambda (x y) (* x y)) and #'(lambda (x y) (* x y)), whereas Graham's original version accepts only the former.
Interestingly in his book Let over Lambda, Doug Hoyte draws attention to a remark by Graham in his book ANSI Common Lisp that being able to omit the #' before a lambda form provides "a specious form of elegance at best" before going on to prefer to omit it.
I'm not taking a stand either way, merely pointing out that given Graham's choice for _f, the absence of the #' is no longer specious but necessary.

Emacs lisp high-order function support

I am trying to implement Haskell-like high-order function in Elisp, using closures.
;;; -*- lexical-binding: t -*-
(defun foo (pair)
(car pair))
(defun* .curry (fn)
(lambda (x y &rest args) (apply fn (cons x y) args)))
((lambda (x y) (1+ x)) 2 3)
((lambda (&rest args) (apply (.curry #'foo) args)) 2 3)
(funcall (.curry #'foo) 2 3)
((.curry #'foo) 2 3)
Problem is that last line returns error Invalid function. So, it seems closure do not considered sane function. I still can use (.curry #'foo) in mapc, but not in hooks.
Is it something I can do about it?
Your ((.curry #'foo) 2 3) is invalid in any Lisp I know of except Scheme (and Scheme derivatives such as Racket). The simplest code that illustrates the issue is as follows:
(defun f () (lambda ()))
(funcall (f)) ; tested in Emacs 23 and CLISP, works
((f)) ; tested in Emacs 23 and CLISP, results in an error

Renaming lambda in Common Lisp

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 _

"unfold" for common lisp?

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.