Возврат сложных структур из функции - паттерн матчинг - Lisp

Узнай цену своей работы

Формулировка задачи:

Несколько раз сталкивался с необходимостью написать функцию, которая возвращает много значений (пар, троек, все это объединено в список), причем функция входит в состав сложной рекурсии и требуется разобрать эти значения, с каждым из них сделать какие-то преобразования и подать в качестве аргументов допустим в ту же функцию, которая опять вернет сложную структуру. И я нередко путался во всех этих caddadadr и т.п В Haskell и других языках для этого очень удобен паттерн-матчинг - он сам разбирает структуру и связывает отдельные ее части с именами указанных формальных параметров, и эти параметры можно использовать в выражениях. В Lisp я краем уха слышал, что функция может возвращать много значений, но во всех ли реализациях так? И как вообще принято поступать в данном случае? Неужели заводить нужное количество внешних переменных и изменять их вместо возврата всего вороха из функции? В общем, в результате подобных мыслей я нарисовал велосипедный макрос. Думаю, в моей реализации он оправдан и принесет желанное количество сахара. А каковы мнения уважаемого сообщества?
(defmacro match (vals args)
    (cond (null? vals) nil
          (null? args) nil
          (symbol? (car args))
              (cond (and (null? (cdr args)) (not (null? (cdr vals))))
                        (def (car args) vals)
                            ((def (car args) (car vals))
                             (match (cdr vals) (cdr args))) )
          (list? (car args))
              ((cond (list? (car vals)) (match (car vals) (car args)))
               (match (cdr vals) (cdr args))) ))
 
(match '(1 (2 (3 4 5 6)) 7 8) '(a (b1 (b2 b3)) c))
(print "a = " a ", b1 = " b1  ", b2 = " b2  ", b3 = " b3 ", c = " c \n)
(match b3 '(d e f))
(print "d = " d ", e = " e ", f = " f \n)
 
a = 1, b1 = 2, b2 = 3, b3 = (4 5 6), c = (7 8)
d = 4, e = 5, f = 6
OK

Решение задачи: «Возврат сложных структур из функции - паттерн матчинг»

textual
Листинг программы
(def A 10 B 20 C 30)
 
(defn test (a b c)
    (def struct (make '((a A) (b B) ((((5 ((c)) (C))))) true)))
    (print \n "struct : " struct \n)
    (match struct '(x y ((((z ((p)) (q))))) b))
    (print "match 1: " (cons x y z p q b) \n)
    (match struct '((x y) z (((p))) b))
    (print "match 2: " (cons x y z p b) \n)
    (match struct '(x (y z) ((((p q)))) a))
    (print "match 3: " (cons x y z p q a) \n) )
 
(test 1 2 3)
 
....
=> 
struct : ((1 10) (2 20) ((((5 ((3)) (30))))) true)
match 1: ((1 10) (2 20) 5 3 30 true)
match 2: (1 10 (2 20) (5 ((3)) (30)) true)
match 3: ((1 10) 2 20 5 (((3)) (30)) true)

Оцени полезность:

8   голосов , оценка 4 из 5