4

Due to my lazy nature, I made something like this:

(defmacro iλ (x)
  `(lambda () (interactive) ,x))

(defmacro iλd (x y)
     `(lambda () ,x (interactive) ,y))

(global-set-key (kbd "<f8>") (iλ (message "hello lambdas")))
(global-set-key (kbd "<f7>") (iλd "Func Docu" (message "hello lambda with docus")))

Due to my lazy nature, I would like to merge these two but it's 10:16pm in the evening and I can't seem to figure it out. I would like something like this (Pseudo code follows):

 (defmacro iλ (x &optional y)   ;y is optional parameter:
  if x & y are defined:
  `(lambda () ,x (interactive) ,y))
  else if only x is defined:  
  `(lambda () (interactive) ,y)
  )

Can this be done, if so how?

[edit solution] As per Malabarba's answer below, I now use the clever bit of code:

(defmacro iλ (x &rest y) 
    (if (and (stringp x) y) 
        `(lambda () ,x (interactive) ,@y) 
      `(lambda () (interactive) ,x ,@y)))
;Example usage:
(global-set-key (kbd "<f8>") (iλ "A message that prints a hello" (message "hello 2")))
(global-set-key (kbd "<f9>") (iλ  (message "hello 1")))
3
  • 1
    In other words you want to treat any parameter whose name begins with an ampersand as if it was optional? This is doable, in a sense, but there are lots of problems associated with it: what about keywords? What about other useful syntax such as &rest? What if you then write (iλ x &x)?
    – wvxvw
    Commented Mar 21, 2015 at 8:24
  • Oh @wvxvw, I was confused X-D. I meant (x &optional y) thank you for pointing this out. Commented Mar 26, 2015 at 21:57
  • I updated question. Commented Mar 26, 2015 at 21:57

1 Answer 1

6

Here's what you're trying to do

(defmacro iλ (x &optional y) 
  (if (and (stringp x) y) 
      `(lambda () ,x (interactive) ,y)) 
    `(lambda () (interactive) ,x ,y)))

And, if you're taking suggestions, here's what I recommend. It should allow you to use any number of forms.

(defmacro iλ (x &rest y) 
  (if (and (stringp x) y) 
      `(lambda () ,x (interactive) ,@y)
    `(lambda () (interactive) ,x ,@y)))

As @Stefan suggests, if you're on Emacs 25 you can do:

(defmacro iλ (&rest body)
  (let ((x (macroexp-parse-body body)))
    `(lambda () ,@(car x) (interactive)
       ,@(cdr x))))
7
  • 2
    With Emacs-25, I'd do (defmacro iλ (&rest body) (let ((x (macroexp-parse-body body))) (lambda () ,@(car x) (interactive) ,@(cdr x))))`.
    – Stefan
    Commented Mar 21, 2015 at 17:05
  • 1
    @Stefan macroexp-parse-body is a good suggestion, but in this particular case a string such as (iλ "return-value") would be confused with a docstring and the resulting lambda would always return nil.
    – Malabarba
    Commented Mar 22, 2015 at 16:01
  • macroexp-parse-body would treat such a lone string as the body, not as the docstring. If you find it doesn't in your case, then please report it as a bug.
    – Stefan
    Commented Mar 22, 2015 at 21:52
  • @Stefan You're right, I was confused.
    – Malabarba
    Commented Mar 23, 2015 at 1:53
  • Awesome. I'll use the 2nd version for now, maybe the E25 version in the future. I think there is a typo thou, the 2nd line has one too many ')' bracket. Removing it makes it work for me. I.e: (defmacro iλlam (x &rest y) (if (and (stringp x) y) (lambda () ,x (interactive) ,@y) (lambda () (interactive) ,x ,@y))) Commented Mar 26, 2015 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.