7

I want to write a function where the only two valid values for the input argument are "dag" or "rulegraph". Is there a way to specify that only these two arguments are accepted this in the elisp function header?

If this is not possible, I'd accept an idiomatic way of handling this.

Drew
  • 75,699
  • 9
  • 109
  • 225
The Unfun Cat
  • 2,393
  • 16
  • 32

2 Answers2

5

Emacs Lisp doesn't have any support for automatic type checking, whether in the byte compiler or at runtime.

The idiomatic way to report an error at runtime is to check the argument against a predicate function, and signal the error `wrong-type-argument if it doesn't match.

Furthermore, to express a choice between a small, fixed number of items, the idiomatic method is to use symbols, not strings.

(defun graph-type-p (object)
  "Return t if OBJECT is a graph type.

The possible graph types are `dag' and `rulegraph'."
  (memq object '(dag rulegraph)))

(defun build-graph (graph-type data)
  "…"
  (unless (graph-type-p graph-type)
    (signal 'wrong-type-argument (list 'graph-type-p graph-type)))
  …)
3

Standard elisp does not allow you to put restrictions on the arguments in the header in the way you're specifying, but you may wish to check out cl-defun in the Common Lisp extension library to get more options in your defuns.

In the meantime, a fairly simple way to handle your use case is to do a preliminary check before you get into the body of the function. Here's a stripped down example:

(defun fnx (arg)
  (unless (member arg '("dag" "rulegraph"))
    (error "Argument must be either \"dag\" or \"rulegraph\""))
  (message "Nice argument"))

(fnx "dag")                             ; => "Nice argument"
(fnx "rulegraph")                       ; => "Nice argument"
(fnx "kittens")                         ; => (ERROR)
(fnx 1)                                 ; => (ERROR)
jch
  • 5,680
  • 22
  • 39
Dan
  • 32,584
  • 6
  • 98
  • 168