Thus, instead of doing (defop r), it's kind of like we're doing (defop (eval r)). That is, instead of expanding into
(defop r req (rpage 'r))
we're expanding into
(defop 10a req (rpage '10a)) ; when r == '10a
(defop 10b req (rpage '10b)) ; when r == '10b
; etc
We could've done the eval inside the macro, too, but that's often a sign you're doing something wrong --- macros are usually there to not evaluate their arguments. So we should probably use a function.
However, defop itself is a macro, so the first parameter (the op's name) won't be evaluated regardless. We still need eval.
Since this approach seems to require eval regardless, we should just look for a better solution. aw's works nicely.
Some other nitpicks over your rewrite (hey, you asked!):
1) Unless you need strings for some reason, you can probably default to symbols (they're a bit easier to use).
; Instead of
(= routes* '("10a" "10b" "15a" "20a" "20b" "30a" "30b" "30c" "40a" "59u"))
; we could use
(= routes* '(10a 10b 15a 20a 20b 30a 30b 30c 40a 59u))
2) Proper spacing & indentation saves lives. :)
; Instead of
(defop shuttle req
(each r routes* (link r)(nbsp)))
; why not
(defop shuttle req
(each r routes* (link r) (nbsp)))
; or even
(defop shuttle req
(each r routes*
(link r)
(nbsp)))
3) Though using symbols renders this point moot, fromstring is unnecessary to simply (read) from a string, since Arc's definition of read is
(def read ((o x (stdin)) (o eof nil))
(if (isa x 'string) (readstring1 x eof) (sread x eof)))
So, instead of
(fromstring rs (read))
you can use
(read rs)
If your goal is just to turn a string into a symbol, you should use
(sym rs)
This is an important distinction. e.g.,
arc> (sym "abc")
abc
arc> (read "abc")
abc
arc> (sym "(a b c)")
|(a b c)|
arc> (type that)
sym
arc> (read "(a b c)")
(a b c)
arc> (type that)
cons
Very instructive. Thank you for doing such a thorough analysis.
',r from your snippet
(mac rdefop (r)
`(defop ,r req (rpage ',r)))
was a realization for me. Never thought of quoting a comma'd symbol in a backquoted expression before, but I like knowing it's possible. Do you find yourself doing this much, or is there usually something simpler like aw's solution available to make it unnecessary?