Just as exercise I want to transform:
(alist "foo" 1 "bar" 2 "baz" 3)
into
(("foo" . 1) ("bar" . 2) ("baz" . 3))
is this possible with syntax-rules?
My attempt:
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y ...)
(list (alist x y) ...))))
the problem that it expand into:
(("foo" . 2) ("foo" . "bar") ("foo" . 4) ("foo" . "baz") ("foo" . 6))
is macro alist possible with syntax-rules? How it should look like?
EDIT:
Another attempt
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y z ...)
(list (alist x y) (alist z ...)))))
it returns (("foo" . 2) (("bar" . 4) ("baz" . 6)))
.
If it's literals only (like "foo"
and 2
) you can just do this:
#!r6rs
(import (rnrs))
(define-syntax alist
(syntax-rules (alist-builder)
((_ alist-builder () (results ...))
'(results ...))
((_ alist-builder (a) . rest)
(raise 'bad-alist))
((_ alist-builder (a b rest ...) (results ...))
(alist alist-builder (rest ...) (results ... (a . b))))
((_ a ...) (alist alist-builder (a ...) ()))))
(alist) ; ==> ()
(alist "a" 2) ; ==> (("a" . 2))
(alist a 3 b 4) ; ==> ((a . 3) (b . 4))
(alist a) ; ==> uncaught exception: bad-alist
Of course you are not allowed to mutate this because (alist a b c d)
is the same as literally writing '((a . b) (c . d))
which you are not allowed to mutate.
Also if you ever make an alist with alist-builder
as the first key the internals will leak. You can fix this by splitting up the internal definition and you can hide it from exposure by having both in a library and only export alist