Name: Anonymous 2013-07-30 10:00
Can you write in C/C++ a destructuring match macro, like following?
;; Usage:
;; (match '(1 2 3 4 5 6) ((a b . c) (list c b a)) (otherwise 'fuck-off))
(defun match-hole (key hole hit miss)
(if (consp hole)
(if (and (eql (car hole) 'quote)
(= (length hole) 2))
`(if (equal ',hole ,key)
,hit
,miss)
(let ((x (gensym))
(hit (match-hole key (cdr hole) hit miss)))
`(if (consp ,key)
(let ((,x (car ,key))
(,key (cdr ,key)))
,(match-hole x (car hole) hit miss))
,miss)))
(if (and (symbolp hole) hole (not (eql hole t)))
(if (string= (symbol-name hole) "_")
hit
`(let ((,hole ,key))
,hit))
`(if (equal ',hole ,key)
,hit
,miss))))
(defmacro match (keyform &body cases)
(let ((key (gensym))
(b (gensym)))
`(let ((,key ,keyform))
(block ,b
(tagbody
,@(reduce (lambda (next case)
(let ((miss (gensym))
(hit `(return-from ,b (progn ,@(cdr case)))))
`(,(match-hole key (car case) hit `(go ,miss)) ,miss ,@next)))
(cons nil (nreverse cases))))))))
;; Usage:
;; (match '(1 2 3 4 5 6) ((a b . c) (list c b a)) (otherwise 'fuck-off))
(defun match-hole (key hole hit miss)
(if (consp hole)
(if (and (eql (car hole) 'quote)
(= (length hole) 2))
`(if (equal ',hole ,key)
,hit
,miss)
(let ((x (gensym))
(hit (match-hole key (cdr hole) hit miss)))
`(if (consp ,key)
(let ((,x (car ,key))
(,key (cdr ,key)))
,(match-hole x (car hole) hit miss))
,miss)))
(if (and (symbolp hole) hole (not (eql hole t)))
(if (string= (symbol-name hole) "_")
hit
`(let ((,hole ,key))
,hit))
`(if (equal ',hole ,key)
,hit
,miss))))
(defmacro match (keyform &body cases)
(let ((key (gensym))
(b (gensym)))
`(let ((,key ,keyform))
(block ,b
(tagbody
,@(reduce (lambda (next case)
(let ((miss (gensym))
(hit `(return-from ,b (progn ,@(cdr case)))))
`(,(match-hole key (car case) hit `(go ,miss)) ,miss ,@next)))
(cons nil (nreverse cases))))))))