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")))
  • 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 Mar 21 '15 at 8:24
  • Oh @wvxvw, I was confused X-D. I meant (x &optional y) thank you for pointing this out. – Leo Ufimtsev Mar 26 '15 at 21:57
  • I updated question. – Leo Ufimtsev Mar 26 '15 at 21:57
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))))
  • 2
    With Emacs-25, I'd do (defmacro iλ (&rest body) (let ((x (macroexp-parse-body body))) (lambda () ,@(car x) (interactive) ,@(cdr x))))`. – Stefan Mar 21 '15 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 Mar 22 '15 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 Mar 22 '15 at 21:52
  • @Stefan You're right, I was confused. – Malabarba Mar 23 '15 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))) – Leo Ufimtsev Mar 26 '15 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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