Возврат сложных структур из функции - паттерн матчинг - 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)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д