Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use of &rest and &key at the same time in Common Lisp

I want to use both &rest and &key at the same time. However, the attempted code below:

(defun test (&rest args &key (name "who")) nil)
(test 1 2 3 4 5 :name "hoge")

causes an error:

*** - TEST: keyword arguments in (1 2 3 4 5 :NAME "hoge") should occur pairwise

and when I gives only keyword parameter like (test :name "hoge"), it works. Is it possible to use both &rest and &key?

like image 278
orematasaburo Avatar asked Jun 22 '19 02:06

orematasaburo


People also ask

How do we use a semicolon?

Use a semicolon to join two related independent clauses in place of a comma and a coordinating conjunction (and, but, or, nor, for, so, yet). Make sure when you use the semicolon that the connection between the two independent clauses is clear without the coordinating conjunction.

When should a semicolon be used examples?

A semicolon may be used between independent clauses joined by a connector, such as and, but, or, nor, etc., when one or more commas appear in the first clause. Example: When I finish here, and I will soon, I'll be glad to help you; and that is a promise I will keep.

What is a semicolon example?

When to Use a Semicolon. A semicolon (;) is a punctuation mark that has two main functions: Semicolons separate items in a complex list. For example, The Council is comprised of ten members: three from Sydney, Australia; four from Auckland, New Zealand; two from Suva, Fiji; and one from Honiara, Solomon Islands.

What is a colon versus a semicolon?

The primary use of semicolons is to join two main clauses. The difference between semicolons and colons is that colons can combine two independent clauses, but their primary use is to join independent clauses with a list or a noun.


2 Answers

The combination of &key and &rest are actually very common in Common Lisp, but almost always together with &allow-other-keys.

E.g., suppose you want to define a wrapper for write but do not want to list explicitly all the keyword arguments it takes:

(defun my-write (object &rest args &key stream &allow-other-keys)
  (write "my wrapper" :stream stream)
  (apply #'write object args))

You will find many places where this &rest/&key/&allow-other-keys patterns is used wherever the CLOS is actually implemented.

like image 53
sds Avatar answered Sep 25 '22 08:09

sds


It's generally not a good idea to mix rest parameters with keyword parameters within a function definition in Common Lisp. If you do so, you should probably consider rewriting the function definition because it can lead to some unexpected behavior. If both &rest and &key appear in a parameter list, then both things happen--all the remaining values, which include the keywords themselves, are gathered into a list that's bound to the &rest parameter, and the appropriate values are also bound to the &key parameters. So the (name "who") keyword parameter is bound to your list of rest parameters by default. if you try to enter the arguments (1 2 3 4 5), you will get an error because they aren't bound to your parameter (name "who"). Here is an example:

(defun test (&rest args &key (name "who"))
   (list args name))

Here we have your function definition. If we try to call the function which return a list of the arguments, we will see that the &rest parameters are bound to they &key parameters here:

CL-USER> (test :name "Davis")
((:NAME "Davis") "Davis")

By mixing &rest parameters and keyword parameters in the same parameter list, you won't be able to enter any rest parameters that don't match your keyword parameter which is why you enter into a breakloop here.

Now, if you want to create a macro, you can technically use multiple parameter lists within the definition, and add keyword parameters in one list, and &rest (or &body) parameters in the other list:

 (defmacro hack-test ((&key (name "who")) &body body)
   `(list ,name ,@body))

CL-USER> (hack-test (:name "Ricky")
                (+ 2 3))
("Ricky" 5)

CL-USER> (hack-test ()
                 (+ 2 4)
                 (+ 4 5)
                 (+ 9 9))
("who" 6 9 18)
CL-USER> 
like image 25
Simeon Ikudabo Avatar answered Sep 24 '22 08:09

Simeon Ikudabo