| As presented, the example macro doesn't demonstrate referential transparency, but then again, the example appears to be incorrect. The issue is invoking "(swapargs (mod 7 5))". I tried this in the Scheme REPL (Chicken to be precise), in which the macro was defined: (define-syntax swapargs
(syntax-rules ()
((_ ls) (list (list-ref ls 0) (list-ref ls 2)
(list-ref ls 1)))))
(swapargs '(a b c)) => (a c b)
(swapargs (swapargs '(a b c))) => (a b c)
In other words, the macro does show referential transparency.However, the following doesn't work: (swapargs (modulo 7 5)) => Error: (list-tail) bad
argument type: 2
The problem is the argument is evaluated first, and "2" is not a list. (The macro requires a list-of-3 argument.) (modulo 7 5) => 2
Probably, what was intended was like this: (swapargs '(module 7 5)) => (modulo 5 7)
And again: (swapargs (swapargs '(module 7 5))) => (module 7 5)
(eval (swapargs '(module 7 5))) => 5
(eval (swapargs (swapargs '(module 7 5)))) => 2
(eval (swapargs (swapargs '(module 10 8)))) => 2
It looks like confusion between literal and evaluable lists prompted the wrong conclusion, but in this case it's simple to rectify.Of course, macros in Scheme/Lisp can easily become convoluted and bug-ridden as much as any code, even aside from arguments about the virtues of "hygienic" vs. "unhygienic" systems. Properly constructed, macros remain an essential feature of Lisp/Scheme languages. BTW, if we're comparing qualities of programming languages, here's a real-life example showing the particular merit of Scheme. I took on the task of creating a complex application (a web server supporting multiple hosts) and decided to write it primarily in Scheme (and some C). The first version was up and running in less than half a year. Inevitably, months after the project was deployed changes were necessary. Despite the length of time since last seen, the code wasn't obscure to me, it was easy to understand and pick up where I'd left off before. Definitely different from prior experiences. The crux is getting a good grasp on its core, macrology perhaps among the harder parts. But understood, Scheme allows enhanced productivity, as I've known it more so than other languages "under load" in parallel situations. |
When you say my example is incorrect, do you mean that it's incorrect in clojure, or only in scheme? I tried my examples in clojure and they appear to work and appear to demonstrate a lack of referential transparency. I assume that clojure is a valid lisp to make a point about metaprogramming and macros.
Also, it looks like it's fairly easy in scheme to show the same thing, which it looks like you started to do (I'm not sure whether you agree with me about that or not):
The two calls to "eval" are identical, yet return different results. That breaks referential transparency."showing the particular merit of Scheme"
From what I know, I like lisps of various flavors. I just said that they didn't really speak to the kinds of problems that I deal with. Maybe if I wrote more lisp I would see why it does so, but currently I do not.