Обычный шепелявый:Работа с параметрами &rest
-
08-07-2019 - |
Вопрос
Кто-нибудь может подсказать мне, как работать с параметрами, хранящимися в значении, указанном &rest.
Я много читал, и кажется, что авторы знают только, как перечислить все параметры таким образом.
(defun test (a &rest b) b)
На это приятно смотреть, но на самом деле не так уж и полезно.
Лучшее, что я нашел на данный момент, - это использовать first, second и так далее, чтобы получить искомый параметр.
(defun test (a &rest b)
(first b))
Я заметил, что этот метод перестает работать при десятом параметре, но спецификация (из того, что я прочитал) поддерживает минимум 50.Даже если шансы на то, что я буду использовать 50 параметров, невелики, я хотел бы знать, как получить доступ ко всем из них.
Спасибо
Решение
ПЕРВАЯ, ВТОРАЯ и так далее функции доступа - это "просто" служебные функции поверх CAR / CDR или NTH.ИТАК, я полагаю, ответ на ваш конкретный вопрос таков: "используйте NTH или ELT" (или создайте свои собственные специфические функции acccessor).
Если вы хотите, вы можете определить ОДИННАДЦАТЫЙ как:
(обезврежен одиннадцатый (список) (n-й список из 10))
Однако я обнаружил, что в основном использую аргументы &REST, когда есть 0 или более вещей, с которыми я хочу что-то сделать, на самом деле не заботясь о конкретной позиции данного аргумента в списке &REST.Обычно это влечет за собой использование LOOP, DO или DOLIST для обхода аргументов и выполнения чего-либо с каждым из них;семейство карт или (иногда) УМЕНЬШИТЬ.
Другие советы
Параметр Rest - это просто список.Вы можете справиться с этим, используя обычные операции со списком.
(defun test (a &rest b))
(dolist (s b)
(when (> s 1)
(print s)
(do-something-else b)))
На самом деле эта функция полезна.Вам нужно только попробовать это.
CL-USER 1 > (defun test (a &rest b) b)
TEST
CL-USER 2 > (test 1 2 3 4)
(2 3 4)
Итак, вы видите, что B - это просто список аргументов.Таким образом, применимы все операции со списком и последовательностью.Здесь нет ничего волшебного.Существуют функции для доступа к N-му элементу, функции для удаления элементов и т.д..
В Common Lisp HyperSpec перечислены соответствующие функции:
17.Словарь Последовательностей
Базовое руководство по лиспу можно найти в книге Турецкого:
Обычный шепелявый:Краткое введение в символьные вычисления
Книгу можно загрузить в формате PDF и Postscript.Он обучает основам Common Lisp.
Вы также могли бы использовать destructuring-bind:
(defun my-function (&rest arguments)
(destructuring-bind (a b &rest c) arguments
(format nil "~A,~A followed with ~A" a b c)))
CL-USER> (my-function 1 2 "Give" 'me "more" 'arguments!!)
==> "1,2 followed with (Give ME more ARGUMENTS!!)"
У меня просто есть рекурсивная итерация, чтобы просмотреть их все, я думаю, dolist лучше, но мне нравится использовать старомодный способ