Home > Archive > Scheme > December 2006 > Re: newbie question: do macros in Lisp and Scheme have equal expressive
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Re: newbie question: do macros in Lisp and Scheme have equal expressive
|
|
| Pascal Costanza 2006-12-11, 7:18 pm |
| mingwu@gmail.com wrote:
> In terms of expressive power, are they equal (in their own language)?
> and do they have any difference?
The default macro system of R5RS Scheme is more restricted than Common
Lisp's macro system, but Scheme' syntax-case (which is going to be part
of R6RS) is more or less on par wrt expressive power.
The other important question is which one is more convenient to use. Of
course, you can decide this only for yourself.
> BTW, which Lisp/Scheme compiler implementation produce the fastest
> executable (x86, Linux)?
Efficiency largely depends on the kinds of problems you want to solve.
Such questions cannot be answered in general.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Rob Warnock 2006-12-11, 7:18 pm |
| Pascal Costanza <pc@p-cos.net> wrote:
+---------------
| mingwu@gmail.com wrote:
| > In terms of expressive power, are they equal (in their own language)?
| > and do they have any difference?
|
| The default macro system of R5RS Scheme is more restricted than Common
| Lisp's macro system, but Scheme' syntax-case (which is going to be part
| of R6RS) is more or less on par wrt expressive power.
+---------------
Plus, many [most?] Scheme implementations provide
CL-style "defmacro" (or equivalent) as an extension.
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Rob Warnock wrote:
> Pascal Costanza <pc@p-cos.net> wrote:
> +---------------
> | mingwu@gmail.com wrote:
> | > In terms of expressive power, are they equal (in their own language)?
> | > and do they have any difference?
> |
> | The default macro system of R5RS Scheme is more restricted than Common
> | Lisp's macro system, but Scheme' syntax-case (which is going to be part
> | of R6RS) is more or less on par wrt expressive power.
> +---------------
>
> Plus, many [most?] Scheme implementations provide
> CL-style "defmacro" (or equivalent) as an extension.
An important ingredient of the Common Lisp macro system is the
&environment parameter that allows you to reason about the lexical
environment in which a macro is expanded. This seems to be typically
missing in Scheme versions of CL-style macros and makes a big difference
wrt expressiveness.
macroexpand-1 and macroexpand are also important elements of the CL
macro system.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> This isn't quite correct - because of referential transparency, CL
> macros cannot replicate the behavior of syntax-rules or syntax-case
> macros. Therefore, CL macros are incomparable with syntax-rules.
That's incorrect. Paul Graham shows in "On Lisp" a number of techniques
how to do this manually, and they are straightforward and require only
local changes to your source code. It's also possible to embed an
extension in CL that adds semi-automatic referential transparency in a
portable way. (I have an implementation, and plan to report on this.)
> Further, in the sense of Felleisen's "On the Expressive Power of
> Programming Languages", adding gensym is not a macro-expressible (in
> the technical sense of that paper) transformation, and thus the
> capacity for hygiene also gives more expressiveness to
> syntax-{rules,case} macros.
I don't get what you want to say here. Could you elaborate?
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Pascal Costanza wrote:
> samth wrote:
>
> That's incorrect. Paul Graham shows in "On Lisp" a number of techniques
> how to do this manually, and they are straightforward and require only
> local changes to your source code. It's also possible to embed an
> extension in CL that adds semi-automatic referential transparency in a
> portable way. (I have an implementation, and plan to report on this.)
>
>
> I don't get what you want to say here. Could you elaborate?
Maybe that's important: I regard gensym (and related symbol
functionality) as an essential ingredient of the CL macro system.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> I'm curious about how the &environment parameter is typically used.
> For example, according to the hyperspec, it seems that these lexical
> environments are used for looking up the functions bound to macro
> names, and as the environment to macroexpand[-1].
The typical use is for code walkers.
> In PLT Scheme, similar features are available ([1], [2]), but they rely
> on the implicit syntactic environment. Is the fact that environments
> are first-class values typically used in CL, or is the current
> environment always the one supplied?
I guess in most cases, it's the one that is supplied. (But, of course,
the only thing I can say for sure about 95% of the cases is that I
haven't seen them... ;)
> In other words, could these CL macros that you describe (of which I'd
> like to see examples) be ported to PLT Scheme's primitives?
>
> [1]
> http://pre.plt-scheme.org/docs/html...l#node_idx_3100
> [2]
> http://pre.plt-scheme.org/docs/html...l#node_idx_3124
I find the descriptions at these links hard to understand without more
context (and I currently don't have the time to study this in more
detail), but indeed sounds like they provide that functionality.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> A new construct is "macro-expressible" if it could be defined as an
> arbitrary macro, roughly. This requires that multiple uses of the new
> construct not have to communicate with each other, since then the
> transformation is global, not local. The addition of the counter for
> gensym is a global, not a local transformation (since we have to define
> the counter variable before the first macro definition, roughly).
OK, I see.
> If we take gensym as a part of the original system, then this concern
> doesn't apply.
That's what I meant with my second response. A CL-style macro system
without something like gensym would indeed be pretty unreliable. But
macros provide a way to transform s-expressions, and symbols together
with the fact that their eq-ness can be relied upon are an essential
ingredient of s-expressions (in Common Lisp).
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Jens Axel Søgaard 2006-12-11, 7:18 pm |
| samth skrev:
> Pascal Costanza wrote:
>
> Can you cite the part of On Lisp you are referring to? In the copy I
> downloaded from the website, the only advice given for avoiding
> referential transparency problems is to give global variables names
> with * at the beginning and end (which is obviously not a universal
> solution, or a local change).
This thread revolved around some of the same issues.
<http://groups.google.com/group/comp...443a82f8?hl=en&>
In particular Pascal C and I got to the conclusion that it is
non-trivial to make CL macros referential transparent, but that instead
CL offer solutions involving packages.
See in particular message 83 to 86, but the entire thread is worth
a read.
--
Jens Axel Søgaard
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
> Pascal Costanza <pc@p-cos.net> writes:
>
>
> There are other important parts in the CL-style macro system that are
> required to avoid unreliable macros.
I mentioned a necessary condition, not a sufficient one. ;)
> One is the need to load files in a particular order.
Same in Scheme. (And both in Scheme and Common Lisp, there are ways to
automate this.)
> Another is the requirement to not modify any
> builtins. Also there's the general trust in the programmer thing --
> it's easy to shoot your feet, but you're expected to avoid doing that.
> (Personally, I don't like shooting anybody's feets including mine, but
> every once in a while I do like to play around with my feet and see
> what happens if I turn them to extra hands or if I rewire them to my
> head -- things that are just not possible in CL.)
This is going too fast: What is it that you cannot do in CL?!?
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> Can you cite the part of On Lisp you are referring to? In the copy I
> downloaded from the website, the only advice given for avoiding
> referential transparency problems is to give global variables names
> with * at the beginning and end (which is obviously not a universal
> solution, or a local change).
There are two cases: global macros and local macros.
For global macros, you can use the package system in CL. This is
described in Chapter 9.7 in "On Lisp".
For local macros, the problem is illustrated with the following example:
(let ((x 42))
(macrolet ((foo () '(print x)))
(let ((x 88))
(foo))))
This prints 88, although you might conclude from the first two lines
that what is actually intended here is to print 42.
The solution to this is to just rename the involved variables. This is
all nested code, so is all written by the same programmer. (If parts of
this code are the result of some macroexpansion, that macro can take
care of hygiene.)
It is true that syntax-rules provides stronger guarantees because it
automatically takes care of referential transparency. (But in turn, this
also complicates other kinds of macros that you might want to express.)
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> What do you mean here? What code is being walked, and why do you need
> an environment? Are you walking expanded code?
Assume you have a macro definition that gets passed some code, and you
want to know more details about that code, for example to optimize the
expansion. The basic approach is to use macroexpand and analyse the
expanded code, roughly like this:
(defmacro m (... &body body &environment env)
(let ((local-expansion (macroexpand body env)))
...))
That's the very rough idea. See http://bc.tech.coop/blog/040512.html for
a few pointers.
Basically, you can use this to implement macros like the ones presented
in Dan Friedman's "Object-oriented Style".
>
> Do you have any examples? I'm genuinely curious.
The example using symbol-macrolet provided at
http://www.lispworks.com/documentat...es/iss066_w.htm is
pretty interesting. It shows one way how the underspecified compiler-let
from pre-ANSI Common Lisp can better be expressed in terms of symbol-macros.
>
> Basically, syntax-local-value is similar to macro-function (but more
> general, in that it can return any value, not just a function), and
> local-expand is like macroexpand (but also more general, since it can
> be instructed not to expand some macros).
OK, so I think the equivalents in Common Lisp are macroexpand on symbol
macros, which can also return any values, not just s-expressions, and
combinations of macroexpand-1 and macroexpand which also allow you to
selectively expand code.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
> Pascal Costanza <pc@p-cos.net> writes:
>
>
> No -- at least not in PLT, when you're using the module system. (And
> that's an important point about "compilable" as in Matthew's paper.)
The module system in PLT _is_ a way to automate the loading of files in
a particular order.
For these purposes, Common Lispers use system definition facilities. The
only difference is that in the PLT Scheme module system, the
dependencies between modules are defined locally in the module
definitions, whereas in system definition facilities, the dependencies
are (declaratively!) defined outside of the respective files. These two
different ways just have different trade offs.
(For example, one advantage of system definition facilities like
mk-defsystem or asdf is that they work portably across different Common
Lisp implementations.)
>
> Here's a quick example:
>
> (module silly-contracts mzscheme
> (provide (all-from-except mzscheme define)
> (rename contracted-define define))
> (define-syntax contracted-define
> (syntax-rules (:)
> [(contracted-define (f [x : xpred?] ...) : fpred? body ...)
> (define (f x ...)
> (unless (xpred? x)
> (error 'f "wrong value for ~s: ~s" 'x x))
> ...
> (let ([result (begin body ...)])
> (if (fpred? result)
> result
> (error 'f "my code is broken: trying to return ~s" result))))]
> [(contracted-define x : pred? val)
> (define x
> (let ([v val])
> (if (pred? v)
> v
> (error 'x "broken definition: trying to bind to ~s" v))))]
> [(contracted-define . whatever)
> (define . whatever)])))
>
> which can be used to replace your `define' -- but still keeping your
> sanity. Note that each use of the new `contracted-define' uses the
> built in `define', and also note that programmers that use this code
> still use a plain `define', which is really my `contracted-define',
> which is really expanding to the built in `define'.
>
> So, in the context of code that uses the above, my left leg is rewired
> to stick out of my forehead, but I can still walk. In CL I'm just not
> allowed to touch it.
Of course, and this is even a very straightforward exercise!
(defpackage :silly-contracts
(:use :common-lisp)
(:shadow :defun :defvar)
(:export :defun :defvar))
(in-package :silly-contracts)
(defmacro defun (name fpred (&rest args) &body body)
`(common-lisp:defun ,name ,(mapcar #'first args)
,@(loop for (x xpred) in args
collect `(assert (,xpred ,x)))
(let ((result (progn ,@body)))
(assert (,fpred result))
result)))
(defmacro defvar (name pred form)
`(common-lisp:defvar ,name
(let ((value ,form))
(assert (,pred value))
value)))
(defpackage :silly-contracts-user
(:use :common-lisp)
(:shadowing-import-from :silly-contracts :defun :defvar))
(in-package :silly-contracts-user)
SILLY-CONTRACTS-USER[7]> (defun foo oddp ((x evenp)) (1+ x))
FOO
SILLY-CONTRACTS-USER[8]> (foo 4)
5
SILLY-CONTRACTS-USER[9]> (foo 5)
*** - (EVENP X) must evaluate to a non-NIL value.
The following restarts are available:
CONTINUE :R1 Retry
ABORT :R2 ABORT
Break 1 SILLY-CONTRACTS-USER[10]> ^D
SILLY-CONTRACTS-USER[11]> (defvar x evenp 4)
X
SILLY-CONTRACTS-USER[12]> (defvar y evenp 5)
*** - (EVENP SILLY-CONTRACTS::VALUE) must evaluate to a non-NIL value.
The following restarts are available:
CONTINUE :R1 Retry
ABORT :R2 ABORT
Better error messages are left as an exercise to the reader. ;)
Again, this is all perfectly portable ANSI Common Lisp.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
> (I'll try to make this short, since we're getting to the diminishing
> returns zone.)
>
> Pascal Costanza <pc@p-cos.net> writes:
>
>
> That's a gross understatement, IMO.
>
>
> Modules are compilation units -- taking a global-namespace facility
> and slapping a loader-sequencing tool doesn't make change things much,
> you still deal with a global REPL with its problems.
The pros and cons of modules vs packages weren't under discussion. The
system definition facilities for Common Lisp do solve the issue of
loading definitions in the right order. If you care about only that
problem, then these two solutions are on par.
>
> And you're still limited to namespace control. (My personal
> experience is that when you start writing code that deals with both
> packages things get ugly fast. But I won't quibble more.)
That's quite a different statement from your original "just not possible
in CL" claim. Personal experiences can vary...
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
|
|
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
> vedm <ns@ns.com> writes:
>
>
> Neither less, nor more. Of course. You could even look at my
> original code:
>
> (module silly-contracts mzscheme
> (provide (all-from-except mzscheme define)
> (rename contracted-define define))
> (define-syntax contracted-define
> [...]))
>
> and remove all of module-related stuff:
>
> (define-syntax contracted-define
> [...])
>
> The result works just as fine -- as long as you use
> `contracted-define' in code that wants to use this. If you're fine
> with that (or with a facility that will twist the current input so
> `define' is used as `define-contract'), then not only was I wrong, but
> there is no use for modules at all. If you go down the
> "TM-equivalent" path, then what you usually get is a flamewar that
> goes nowhere -- and one of the major lessons of the expressiveness
> paper is that TM-equivalence is as bogus as it is.
The TM-equivalence argument is nonsense here. It's absolutely possible
to "redefine" standard Common Lisp definitions for your own programs.
It's not only possible, but also routine to do so. I am using this in my
own projects, and have seen this in quite a few others as well. Common
Lispers don't seem to have serious problems with this.
It's true that the features that we have discussed in our subthread are
tied to the PLT module system, and that Common Lisp misses some other
features of such an advanced module system. But the specific things you
claimed are impossible in CL are definitely possible, straightforwardly
so, and used in practice.
See also http://www.research.att.com/~bs/bs_faq.html#compare
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
>
> Here's a quick example:
[...]
....which I still think is invalid. However, I recall that the PLT module
system allows you to redefine function application within a module (by
overriding some internal apply operator). That's something that's indeed
not possible in Common Lisp, and would have been handy in some of my
language extension experiments.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Eli Barzilay wrote:
> Pascal Costanza <pc@p-cos.net> writes:
>
>
> If you're willing to accept certain global modifications to your code
> then you won't see a problem. In your example, that would be the use
> of `common-lisp:defun' and `common-lisp:defvar' (the explicit package
> qualification). (And this is the same thing that happens in
> TM-dead-threads.)
I am not following you. What is it that you are referring to when you
say "global modifications"?
Both in the Common Lisp package system and in the PLT module system,
there is only one entity that you can refer to with one name. If you
want to have two defun versions, at least one of them has to be
qualified in Common Lisp. If want to have two define versions, at least
one of them has to be renamed in PLT. What's the big difference here?
Both CL packages and PLT modules allow you to create local "worlds" with
different language definitions. PLT modules "just" provide stronger
encapsulation guarantees.
>
> [Well, my example failed to point at the problems that you get when
> you try to wire up packages in more complex ways. Not surprising,
> given that it was only a limited toy.]
Can you give an example in which packages fail?
>
> [I certainly don't want to make this thread longer than it is.
> Returns have diminished away to zero.]
What do you suggest to increase the potential returns?
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Marcus Breiing wrote:
>
> Exactly. But I still doubt that referential transparency can be so
> achieved. That doesn't mean I have a proof that it's impossible, but
> in the absence of evidence to the contrary, I'm skeptical.
It's important to see this in the context of the common practice in the
language under discussion.
As I already tried to explain elsewhere in this thread, there are two
cases, global macros and local macros. With global macros, you do the
following in Common Lisp:
(defun some-auxiliary-function (...)
;; You don't want this to interfere with other code
...)
(defmacro some-macro (...)
;; This expands to an invocation of some-auxiliary-function
`(... (some-auxiliary-function ...) ...))
To ensure that in expansions, there will not be any conflicts here, the
following steps are sufficient to ensure "referential transparency":
- Use a good and descriptive name for the auxiliary function.
(Admittedly, this doesn't ensure anything, but helps a lot.)
- Put both definitions in a package, and export some-macro but not
some-auxiliary-function. This ensures that code using some-macro in
other packages won't have any conflicts with some-auxiliary-function.
With local macros, the following or similar cases "hurt":
(let ((x 42))
(macrolet ((foo () 'x))
(let ((x 88))
(+ x (foo)))))
The solution is to just not do this. This your own code, so you have all
the names under control. Write this instead:
(let ((x 42))
(macrolet ((foo () 'x))
(let ((y 88))
(+ y (foo)))))
The one case that indeed seems impossible to achieve is this:
(let ((x 42))
(defmacro foo () 'x))
This creates a global macro foo that expands into 'x, presumably to
refer to the local variable x. This code simply doesn't make sense in
Common Lisp. You would say the following instead:
(defvar *x* 42)
(defmacro foo () '*x*)
....and use packages to ensure hiding the variable name from other code.
We are actually back to the global case here...
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| Abdulaziz Ghuloum wrote:
> Pascal Costanza wrote:
>
> Let's leave macros aside for a minute and rewrite the first program
> using boring code only:
>
> (let ((x 42))
> (flet ((foo () x))
> (let ((x 88))
> (+ x (foo)))))
>
> We both agree, I presume, that the correct value of this program must
> be 130. Emacs-lispers would protest: But we want the answer to be 176!
> Emacs-lispers, after all, know that "the solution is to just not do
> this." They would gladly show you how to rewrite that example as:
>
> (let ((x 42))
> (flet ((foo () x))
> (let ((y 88))
> (+ y (foo)))))
>
> They might even add: "this is your own code, so you have all the names
> under control."
>
> So, Pascal, do you buy this "solution"?
Ah, excellent. This is exactly the question that allows me to make my
point very clear!
In Common Lisp, I can get both results very easily:
(let ((x 42))
(flet ((foo () x))
(let ((x 88))
(+ x (foo)))))
=> 130
(let ((x 42))
(declare (special x))
(flet ((foo () x))
(let ((x 88))
(declare (special x))
(+ x (foo)))))
=> 176
Likewise, I can get both results very easily with CL-style macros:
(let ((x 42))
(macrolet ((foo () 'x))
(let ((y 88))
(+ y (foo)))))
=> 130
(let ((x 42))
(macrolet ((foo () 'x))
(let ((x 88))
(+ x (foo)))))
=> 176
For all four cases, I can imagine situations in which these different
results are respectively the correct results.
With syntax-rules, I can get only one of the possible results, i.e.,
130. I don't see how to make the code return 176, at least not in a
straightforward way. [1]
My original statement in this thread was this:
> The default macro system of R5RS Scheme is more restricted than
> Common Lisp's macro system, but Scheme' syntax-case (which is going
> to be part of R6RS) is more or less on par wrt expressive power.
I regard syntax-rules to be more restricted than CL-style defmacro,
because I can very easily get two reasonable semantics out of CL-style
defmacro, while I can get only one out of syntax-rules.
> The other important question is which one is more convenient to use.
> Of course, you can decide this only for yourself.
....I still stand to both claims.
Pascal
[1] The following "solution" is ruled out for obvious reasons:
(let ((x 42))
(let-syntax ((foo (syntax-rules ()
((foo) x))))
(let ((x 88))
176)))
;-)
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
| |
| Pascal Costanza 2006-12-11, 7:18 pm |
| samth wrote:
> Pascal Costanza wrote:
>
> [snip a long discussion about how to name your variables]
>
> That was a very comprehensive survey about how to name your variables
> and use packages to avoid referential transparency issues. However, in
> the example you gave:
>
> (let ((x 42))
> (macrolet ((foo () 'x))
> (let ((x 88))
> (+ x (foo)))))
>
> There is nothing you can change the body of the `foo' macro to that
> causes the result to be 130, *without changing the rest of the
> example*. That's what not having referential transparency means. By
> contrast, with Scheme macros, the result is always 130, regardless of
> the naming of the variable.
This is all correct.
> I realize this property may not be important to you, and you may think
> the effort required to avoid this issue is worth it for a "simpler"
> macro system. But defmacro macros are not referentially transparent.
This is also correct.
What's important to me in a language construct is first, whether I can
express variations on reasonable semantics or not depending on the
circumstances, and second, whether it is convenient to use, exactly in
this order. I especially distrust preconceived notions of "correctness",
but that's probably just my personal take on such matters.
See my previous response to Aziz for more details.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
|
|
|
|
|