Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have optional arguments AND keyword arguments to the same function?

I am trying to write a Lisp function that can take optional and keyword arguments. The function begins

(defun max-min (v &optional max min &keyword (start 0) (end nil))

When I try to call the function using the keyword arguments but not the optional ones, I get an error. What I'm trying to do is

(max-min #(1 2 3 4) :start 1 :end 2)

I'm getting the error Error: :START' is not of the expected type REAL'

I assume that this is because it is trying to bind :start to max. How can I get this to work? Thanks.

like image 329
Daniel Avatar asked Nov 13 '11 02:11

Daniel


People also ask

How can I pass optional or keyword parameters from one function to another?

Users can either pass their values or can pretend the function to use theirs default values which are specified. In this way, the user can call the function by either passing those optional parameters or just passing the required parameters. Without using keyword arguments. By using keyword arguments.

How do you pass optional or keyword arguments in Python?

You can define Python function optional arguments by specifying the name of an argument followed by a default value when you declare a function. You can also use the **kwargs method to accept a variable number of arguments in a function.

Can a function define arguments and keyword arguments?

In Python, you can define a function that takes variable number of arguments. In this article, you will learn to define such functions using default, keyword and arbitrary arguments.

Can we have multiple arguments in function?

Some functions are designed to return values, while others are designed for other purposes. We pass arguments in a function, we can pass no arguments at all, single arguments or multiple arguments to a function and can call the function multiple times.


2 Answers

You need to call that function with the required parameter, the optional parameters and then the keyword parameters. How should it work otherwise? Your call lacks the optional parameters. If you want to specify keyword parameters in the call, the optional are no longer optional.

(max-min #(1 2 3 4) 0 100 :start 1 :end 2)

The basic style rule:

Don't mix optional with keyword parameters in a function. Common Lisp for example uses it in some place and it is a source of bugs.

CL:READ-FROM-STRING is such an example.

read-from-string string
                 &optional eof-error-p eof-value
                 &key start end preserve-whitespace

http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_fro.htm

This works:

(read-from-string " 1 3 5" t nil :start 2)

This may work also:

(read-from-string " 1 3 5" :start 2)

But the user forgot to specify the EOF-ERROR-P and EOF-VALUE. The Lisp compiler may not complain and the user will wonder why it won't start at 2.

like image 125
Rainer Joswig Avatar answered Nov 15 '22 10:11

Rainer Joswig


For completeness' sake, you can technically get it to work by parsing the list of supplied arguments yourself:

(defun max-min (v &rest args)
  (flet ((consume-arg-unless-keyword (default)
           (if (keywordp (first args))
               default
               (pop args))))
    (let ((max (consume-arg-unless-keyword nil))
          (min (consume-arg-unless-keyword nil)))
      (destructuring-bind (&key (start 0) (end nil)) args
        ;; ...
        ))))

As usual, though, it's a good idea to listen to Rainer. This looks like too magical a design. It confuses both the development environment (by breaking automatic arglist display, for instance) and the user (by making type errors harder to find: what happens when you accidentally pass a keyword where you intended to pass a number?).

like image 32
Matthias Benkard Avatar answered Nov 15 '22 09:11

Matthias Benkard