Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make named arguments in ELisp?

Tags:

emacs

elisp

I figured that since Emacs Lisp and Common Lisp seemed so closely related syntax wise, I could just follow the example code I found on RosettaCode, but it turns out that I was wrong.

The code in question looks like this:

(defun print-name (&key first (last "?"))
  (princ last)
  (when first
    (princ ", ")
    (princ first))
  (values))

And according to RosettaCode it should do the following:

> (print-name)
  ?
> (print-name :first "John")
  ?, John
> (print-name :last "Doe")
  Doe
> (print-name :first "John" :last "Doe")
  Doe, John

Now, here's the thing; whenever I try to run that function in my ELisp interpreter, I get the following error:

*** Eval error ***  Wrong number of arguments: (lambda (&key first (last "?")) (princ la\
st) (if first (progn (princ ", ") (princ first))) (values)), 0

I'm not routined enough in lisp to know what that's supposed to mean, and no amount of Googling has lead me any closer to an answer.

So what's the correct way of doing this in Emacs Lisp?

like image 711
Electric Coffee Avatar asked Sep 29 '14 14:09

Electric Coffee


People also ask

What is an argument in Lisp?

What are arguments? Lisp programming is all about defining functions. Functions are general-purpose chunks of a program, and the arguments to a function are the specific data that you ask the function to deal with when you call the function.

How do you create a function in a lisp?

Use defun to define your own functions in LISP. Defun requires you to provide three things. The first is the name of the function, the second is a list of parameters for the function, and the third is the body of the function -- i.e. LISP instructions that tell the interpreter what to do when the function is called.

What is apply in Lisp?

In Common Lisp apply is a function that applies a function to a list of arguments (note here that "+" is a variadic function that takes any number of arguments): (apply #'+ (list 1 2)) Similarly in Scheme: (apply + (list 1 2))

How do I run a function in Emacs?

This function can be run simply. The command [Alt][x] is used to a run a function interactively. Typing [Alt][x] switches the focus in Emacs to the minibuffer - if you then type in a function name it will be executed. To run doodlebug simply type [Alt][x] and then doodlebug.


1 Answers

Since Emacs Lisp does not support keyword arguments directly, you'll need to emulate these, either with cl-defun as in the other answer, or by parsing the arguments as plist:

(defun print-name (&rest args)
  (let ((first (plist-get args :first))
        (last (or (plist-get args :last) "?")))
    (princ last)
    (when first
      (princ ", ")
      (princ first))))

&rest args tells Emacs to put all function arguments into a single list. plist-get extracts a value from a property list, that is, a list of the format (key1 value1 key2 value2 …). Effectively, a plist is a flattened alist.

Together this lets you call print-name just like in your question:

> (print-name)
  ?
> (print-name :first "John")
  ?, John
> (print-name :last "Doe")
  Doe
> (print-name :first "John" :last "Doe")
  Doe, John
like image 86
lunaryorn Avatar answered Oct 08 '22 04:10

lunaryorn