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.
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.
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.
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.
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.
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.
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?).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With