LINUX.ORG.RU

[common lisp] Использование одновременно &rest и &key в defun

 


0

0

Не компилирует такую функцию:

(defun form (&key (action "" action-p) (type "" type-p) &rest args) ...)

Пишет misplaced &REST in lambda list: (&KEY (ACTION «» ACTION-P) (TYPE «» TYPE-P) &REST ARGS).

Переставляю &rest в начало:

(defun form (&rest args &key (action "" action-p) (type "" type-p)) ...)
- компилирует, но когда я вызываю
(form "s")
, подразумевая, что args должен быть равен (list «s»), он выходит в отладчик с сообщением «odd number of &KEY arguments».

Вот такое

(z:form :action "submit" :type "Submit")
работает нормально.

Как добиться того, чтобы можно было вызывать функцию с &key параметрами, которые указываются стандартно: ":action «fuck.html»", а все остальные параметры шли в args, вот типа так:

(z:form :action "submit" :type "Submit" "this" "must" "be" "in" "args")

SBCL 1.0.29.11.debian

★★

Вот такое

(z:form :action "submit" :type "Submit")
работает нормально.

Забыл сказать, что это у меня все в пакете под названием «z», хотя я очень сомневаюсь, что это играет какую-либо роль.

bk_ ★★
() автор топика

Может стоит таки PCL почитать?

Вы можете безопасно комбинировать остаточные и именованные параметры, но вначале поведение может показаться немного удивительным. Обычно, наличие либо остаточных, либо именованных параметров приведет к тому, что значения, оставшиеся после заполнения всех обязательных и необязательных параметров, будут обработаны определенным образом – либо собраны в список (для остаточных параметров), или присвоены соответствующим именованным параметрам. Если в списке параметров используются и остаточные и именованные параметры, то выполняются оба действия – все оставшиеся значения собираются в список, который присваивается параметру &rest, а также соответствующие значения присваиваются именованным параметрам.

archimag ★★★
()
Ответ на: комментарий от archimag

Никак нельзя сделать так, чтобы в &rest НЕ СОБИРАЛИСЬ именнованные параметры, а собирались только все, кроме них?

bk_ ★★
() автор топика
Ответ на: комментарий от archimag

Я спрашиваю, можно так сделать или нет.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

>Никак нельзя сделать так, чтобы в &rest НЕ СОБИРАЛИСЬ именнованные параметры, а собирались только все, кроме них?

Можно сделать макру defun* в которой принимать &rest и &key, а после этого из &rest выпиливать все &key'и. Я когда-то писал, между делом поищу.

Sectoid ★★★★★
()
Ответ на: комментарий от Sectoid

Я сделал так - для моих потребностей как-раз хватает.

(defun f (&rest args)
  (let ((known-properties (list "action" "name" "type"))
	(properties-list nil)
	(content-list nil)
	(current-string-index 0))
    (loop
       (if (>= current-string-index (length args))
	   (return))
       (if (find (nth current-string-index args) known-properties :test #'equal)
	   (progn
	     (push (nth (1+ current-string-index) args) properties-list)
	     (push (nth current-string-index args) properties-list)
	     (setq current-string-index (+ current-string-index 2)))
	   (progn
	     (loop for i from current-string-index to (1- (length args)) do
		  (push (nth i args) content-list))
	     (return))))
    (format t "properties: ~a~%" properties-list)
    (format t "content   : ~a~%" content-list)))

bk_ ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.