I've been thinking about the use of macros in Lisp, and it seems to me
that the ones I've seen (e.g. IF*, WITH-OPEN-FILE) are really
functions that want a code block as argument, but the user doesn't
want to keep typing LAMBDA.
If LAMBDA had a shorter spelling, would macros still be needed? For
example, in Smalltalk LAMBDA is spelled [] so things like IF are
higher-order functions, no macros required.
But are there practical examples of macros that could not be expressed
as higher-order functions even if LAMBDA was short enough that you
didn't mind typing it on every call?
--
"Sore wa himitsu desu."
To reply by email, remove
the small snack from address.
http://www.esatclear.ie/~rwallace
················@eircom.net (Russell Wallace) wrote in message news:<·················@news.eircom.net>...
> If LAMBDA had a shorter spelling, would macros still be needed?
This is basically the ``do inlined higher order functions make macros
unnecessary'' question.
The answer is no, because macros do more than simply arrange
evaluation orders and rules for functional blocks. They do more than
generate bodies of inline functions.
Macros can parse arbitrary syntax and, in translating it, give it
semantics. They don't just play games with opaque chunks of the
program; they destructure program source code, analyze and synthesize.
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
How about the standard LOOP macro? A clause like ``for x in
this-list'' isn't some body of code that you can just throw at the
evaluator. The macro has to grok the syntax.
On 5 Apr 2004 13:59:21 -0700, ···@ashi.footprints.net (Kaz Kylheku)
wrote:
>This is basically the ``do inlined higher order functions make macros
>unnecessary'' question.
>
>The answer is no, because macros do more than simply arrange
>evaluation orders and rules for functional blocks. They do more than
>generate bodies of inline functions.
>
>Macros can parse arbitrary syntax and, in translating it, give it
>semantics. They don't just play games with opaque chunks of the
>program; they destructure program source code, analyze and synthesize.
So it would seem - thanks to everyone who provided examples! So the
answer seems to be yes, macros are indeed useful whatever other
facilities you have.
--
"Sore wa himitsu desu."
To reply by email, remove
the small snack from address.
http://www.esatclear.ie/~rwallace
Russell Wallace wrote:
> I've been thinking about the use of macros in Lisp, and it seems to me
> that the ones I've seen (e.g. IF*, WITH-OPEN-FILE) are really
> functions that want a code block as argument, but the user doesn't
> want to keep typing LAMBDA.
But it is not the only reason. I also use macros so I do not have to
type '. I do not mind typing ', but where an embedded language is
a-borning, I like to make it look smoother. I also get huge use out of
variable capture in Cells, so macros meen I so not have to keep typing
"self", a Smalltalkian anaphor injected into rules by the rule-declaring
macro C? C? supplies not just the lambda but also, well, here ya go:
(make-instance 'nuke-button
:enabled (c? (eql (job-title *user*) 'president)) ;; uh-oh
:visible (c? (^enabled))) ;; hide if not authorized
The ^enabled macro supplies the "self" arg to the enabled accessor.
Where did self come from? Variable capture of the binding supplied by C?:
(CELLS::MAKE-C-DEPENDENT :CODE '((^ENABLED))
:RULE (C-LAMBDA (ENABLED SELF)))
Note that the macro is actually generating a call to the constructor of
a type of cell, c-dependent. And isn't that cute, it takes time to
capture the symbolic rule in a slot for debugging. But where is "self"?
Well, a few C?-style macros need to generate lambdas with the same
signature (it is an attribute of the Cells engine, really) so relatively
recently I broke down and created a macro which expands into a lambda
form with the standard signature:
(LAMBDA (#:G1000 &AUX (SELF (CELLS::C-MODEL #:G1000))
(.CACHE (CELLS::C-VALUE #:G1000)))
(DECLARE (IGNORABLE .CACHE SELF))
(ENABLED SELF)))
Note that at this point of the expansion we have gotten into the
internals of the Cells engine. G1000 will be bound to the cell instance,
something users should not be thinking about. SELF, the thing they
should be thinking about, gets bound in an aux binding to a particular
internals slot of the cell. .CACHE likewise.
I think the short answer is that, when something as wicked cool as
macros gets created, you never know what some nut-job will do with them.
I surprised even myself. Now that I have ^enabled -> (enabled self), and
since I like to use self as the first arg to any function (not just cell
rules), I now find myself using stuff like (^enabled) outside rules. I
like the self-documenting quality of knowing the slot used is that of
the function target, as well as the brevity.
>
> If LAMBDA had a shorter spelling, would macros still be needed? For
> example, in Smalltalk LAMBDA is spelled [] so things like IF are
> higher-order functions, no macros required.
>
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
yes, no, yes. :)
kt
--
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
I think that maybe 50% or more of the uses or macros are like this.
Take for example dolist and the more basic loop constructs.
Or even something like with-open-file.
High order functions can do many of the same types of creating extra context
as
macros (handler blocks, unwind protect, additional state and variables).
Naturally though, they don't generate new code, or parse new language
constructs,
or change the meaning of the body code through code translation like macros.
e.g.
(with-equal-keys (case ... ))
(sql (select ...))
meta parsing
generate a parser, from a parser description sublanguage.
Rene.
"Russell Wallace" <················@eircom.net> wrote in message
······················@news.eircom.net...
> I've been thinking about the use of macros in Lisp, and it seems to me
> that the ones I've seen (e.g. IF*, WITH-OPEN-FILE) are really
> functions that want a code block as argument, but the user doesn't
> want to keep typing LAMBDA.
>
> If LAMBDA had a shorter spelling, would macros still be needed? For
> example, in Smalltalk LAMBDA is spelled [] so things like IF are
> higher-order functions, no macros required.
>
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
>
> --
> "Sore wa himitsu desu."
> To reply by email, remove
> the small snack from address.
> http://www.esatclear.ie/~rwallace
················@eircom.net (Russell Wallace) writes:
> I've been thinking about the use of macros in Lisp, and it seems to
> me that the ones I've seen (e.g. IF*, WITH-OPEN-FILE) are really
> functions that want a code block as argument, but the user doesn't
> want to keep typing LAMBDA.
>
> If LAMBDA had a shorter spelling, would macros still be needed? For
> example, in Smalltalk LAMBDA is spelled [] so things like IF are
> higher-order functions, no macros required.
>
> But are there practical examples of macros that could not be
> expressed as higher-order functions even if LAMBDA was short enough
> that you didn't mind typing it on every call?
You might take a look at this chapter from my upcoming book:
<http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html>
In it I build a simple test framework, largely using macros. There
are a couple characteristics of this problem that more or less require
the use of macros. 1) The whole point is to define a concise language
for expressing test cases; I don't want the user to have to write
*anything* beyond the minimum necessary to express the thing to be
tested. 2) (And this is the big one) the test framework needs to see
the test cases both as code to run *and* data so it can report the
test results using the test case itself as the label. If I wrapped the
test cases in lambdas, they'd become opaque.
-Peter
--
Peter Seibel ·····@javamonkey.com
Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Marco Baringer
Subject: Re: Macros still needed with shorter LAMBDA?
Date:
Message-ID: <m2r7v2o63o.fsf@bese.it>
················@eircom.net (Russell Wallace) writes:
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
there are really two kinds of macros:
1) "templates" - these exist just to save you from having to write the
same code over and over again. i'd guess 70/80% of all macros are
just templates. eg: with-open-file, dotimes, with-collector.
these could be re-written as functions.
2) "macros" - these actually change the way the code works, they
inspect and modify the code they were passed. eg: loop, if-bind,
series, with-call/cc.
these could not be rewritten as functions.
--
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
Russell Wallace wrote:
> I've been thinking about the use of macros in Lisp, and it seems to me
> that the ones I've seen (e.g. IF*, WITH-OPEN-FILE) are really
> functions that want a code block as argument, but the user doesn't
> want to keep typing LAMBDA.
Macros abstract over syntax. There's no other way to achieve that. If you
don't use macros, you need a lot of extra keystrokes.
But to make this more concrete:
Another use for macros is to create new binding constructs, e.g. you want to
initialize some variables in a particular way and have them be available in
a particular block of code. Of course, we already have various variations
on LET (many of them based on lambda, at least theoretically), but other
macros often combine binding with the delaying use you mention.
If you remove macros entirely, then would you also remove all the constructs
that are already implemented with macros in Lisp? That sort of answers the
question in itself: would you want to restrict the language so that the
kinds of things that the designers of e.g. CLOS and CL itself were able to
do, will not be possible for ordinary users?
> If LAMBDA had a shorter spelling, would macros still be needed?
> For example, in Smalltalk LAMBDA is spelled [] so things like IF
> are higher-order functions, no macros required.
Heh - because they don't have macros, Smalltalk users worry about how to
implement things like case statements, and write articles on the subject.
Of course, this inability of the language to plausibly implement such a
basic construct is justified on the grounds that you shouldn't be doing it
anyway:
http://c2.com/cgi/wiki?CaseStatementsConsideredHarmful
But still, that doesn't stop Smalltalkers from trying. See e.g.:
http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-July/023867.html
Note that in the example quoted in the message, "all possibilities are tried
rather than just the one that matches the receiver". See what happens when
you don't have macros?
To get a feel for the issue, try writing CASE or COND as an ordinary
function in Lisp and see what you end up with. It's not just about the
delaying required for each branch, it's also how you make the matching
happen without requiring a lot of syntax repeated over and over for every
branch. A naive attempt might look like (using backslash as pseudocode for
a concise lambda):
(cond expr
(list (\ x match-expr1) (\ action-expr2))
(list (\ x match-expr2) (\ action-expr2))
...)
This version avoids the problem mentioned in the Smalltalk version, since
the match expressions are delayed with lambda. I included the LISTs for
effect, of course you don't absolutely need them in this case, but in a real
COND we have parenthetical grouping of the branches that helps syntactic
clarity, too - and that syntactic clarity and conciseness is often one of
the major reasons for macros.
Next, think about performance. Since COND is now a function, when an
expression like the above evaluates, it involves evaluating n*2 lambdas
where n is the number of branches. This creates n*2 procedures every time
the COND is executed, and each time around, only two of those procedures are
used, i.e. 1/n of the number of procedures created. Effectively, this would
cause every Lisp program to suddenly mushroom in terms of the size of the
code that actually has to be evaluated during normal execution.
Put it this way: Lisp wouldn't be winning any performance tests against C if
it worked this way.
Functional languages like Haskell & OCaml have lightweight lambda syntax.
For example, in Haskell, a lambda expression to double a number looks like
(\x -> x*2). Parentheses are optional but commonly needed for grouping.
OCaml is similar.
However, Haskell systems notoriously rely on CPP (the C preprocessor) to
achieve limited and unintegrated macro functionality. OCaml has bowed to
inevitability with a very powerful external macro processor, Camlp4 (
http://caml.inria.fr/camlp4/ ).
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
Summarizing the above, the answer to this question is (a) it's not just
about lambda, not by a long shot; (b) any non-zero length for lambda is too
long to type on every call; and (c) do you really want all those extra
lambdas to be evaluated and the resulting procedures discarded on every
call?
Anton
Anton van Straaten wrote:
> Heh - because they don't have macros, Smalltalk users worry about how to
> implement things like case statements, and write articles on the subject.
> Of course, this inability of the language to plausibly implement such a
> basic construct is justified on the grounds that you shouldn't be doing it
> anyway:
> http://c2.com/cgi/wiki?CaseStatementsConsideredHarmful
>
> But still, that doesn't stop Smalltalkers from trying. See e.g.:
> http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-July/023867.html
>
> Note that in the example quoted in the message, "all possibilities are tried
> rather than just the one that matches the receiver". See what happens when
> you don't have macros?
>
> To get a feel for the issue, try writing CASE or COND as an ordinary
> function in Lisp and see what you end up with. It's not just about the
> delaying required for each branch, it's also how you make the matching
> happen without requiring a lot of syntax repeated over and over for every
> branch. A naive attempt might look like (using backslash as pseudocode for
> a concise lambda):
[SNIP]
I agree with much of what you're saying, but it's entirely possible
to do a very decent "functional" COND and CASE in CL with bearable
syntax. COND is fairly painless:
(defun kond (&rest clauses)
(loop for (condition consequent) on clauses by #'cddr do
(when (funcall condition)
(return-from kond (funcall consequent)))))
(set-macro-function #\[
(lambda (stream c)
(declare (ignore c))
`(lambda () ,(read-delimited-list #\] stream t)))
(set-macro-function #\]
(get-macro-function #\))
and then
(kond
[condition1] [consequent1]
[condition2] [consequent2]
...)
which is actually less syntax-heavy than the real COND.
This is not to its advantage, of course, but syntax-heaviness
isn't the problem. CASE isn't much harder.
(defun kase (value &rest clauses)
(loop for (good-values consequent) on clauses by #'cddr do
(when (or (eq good-values t)
(member value good-values))
(return-from kase (funcall consequent)))))
and then
(kase expr
'(a b c) [...handle-a-b-or-c...]
'(1 2 3) [...handle-1-2-or-3...]
t [...handle-others...])
It might be advisable to hand the result of evaluating EXPR
to whatever consequent gets called. (Not that there's any
such feature in languages like C++ or Pascal.) In that, um,
case (and in any case, for other reasons) we'd want a more
flexible terse way of writing lambda expressions. So ...
(set-macro-function #\[
(lambda (stream c)
(declare (ignore c))
(let ((body (read-delimited-list #\] stream t)
(args ()))
(let ((tail (member '! body)))
(when tail
(setf args (ldiff body tail)
body (rest tail))))
`(lambda ,args . ,body))))
(kase expr
'(a b c) [ x ! ...handle-a-b-or-c...]
'(1 2 3) [ x ! ...handle-1-2-or-3...]
t [ x ! ...handle-others...])
I don't see any particular need for the match expressions
to be delayed. No analogous delaying happens in CL's CASE.
> Next, think about performance. Since COND is now a function, when an
> expression like the above evaluates, it involves evaluating n*2 lambdas
> where n is the number of branches. This creates n*2 procedures every time
> the COND is executed, and each time around, only two of those procedures are
> used, i.e. 1/n of the number of procedures created. Effectively, this would
> cause every Lisp program to suddenly mushroom in terms of the size of the
> code that actually has to be evaluated during normal execution.
Given some way of communicating to the compiler that KOND and KASE
should always be inlined and that the loops inside them should always
be fully unrolled when possible, I don't see any reason why they
shouldn't end up producing pretty much the exact same code as we
get from a real COND or CASE.
--
Gareth McCaughan
.sig under construc
Gareth McCaughan wrote:
> Anton van Straaten wrote:
>>To get a feel for the issue, try writing CASE or COND as an ordinary
>>function in Lisp and see what you end up with. It's not just about the
>>delaying required for each branch, it's also how you make the matching
>>happen without requiring a lot of syntax repeated over and over for every
>>branch. A naive attempt might look like (using backslash as pseudocode for
>>a concise lambda):
>
> [SNIP]
>
> I agree with much of what you're saying, but it's entirely possible
> to do a very decent "functional" COND and CASE in CL with bearable
> syntax. COND is fairly painless:
>
> (defun kond (&rest clauses)
> (loop for (condition consequent) on clauses by #'cddr do
> (when (funcall condition)
> (return-from kond (funcall consequent)))))
>
> (set-macro-function #\[
> (lambda (stream c)
> (declare (ignore c))
> `(lambda () ,(read-delimited-list #\] stream t)))
>
> (set-macro-function #\]
> (get-macro-function #\))
Uh, now can can you show us the short painless "functional"
implementation of LOOP? If you're not going to have macros, you'll have
to implement that too...
paul ain't turing equivalence wonderful
Paul Wallich <··@panix.com> writes:
> Gareth McCaughan wrote:
>
> > Anton van Straaten wrote:
>
> >>To get a feel for the issue, try writing CASE or COND as an ordinary
> >>function in Lisp and see what you end up with. It's not just about the
> >>delaying required for each branch, it's also how you make the matching
> >>happen without requiring a lot of syntax repeated over and over for every
> >>branch. A naive attempt might look like (using backslash as pseudocode for
> >>a concise lambda):
> > [SNIP]
> > I agree with much of what you're saying, but it's entirely possible
> > to do a very decent "functional" COND and CASE in CL with bearable
> > syntax. COND is fairly painless:
> > (defun kond (&rest clauses)
> > (loop for (condition consequent) on clauses by #'cddr do
> > (when (funcall condition)
> > (return-from kond (funcall consequent)))))
> > (set-macro-function #\[
> > (lambda (stream c)
> > (declare (ignore c))
> > `(lambda () ,(read-delimited-list #\] stream t)))
> > (set-macro-function #\]
> > (get-macro-function #\))
>
> Uh, now can can you show us the short painless "functional"
> implementation of LOOP? If you're not going to have macros, you'll
> have to implement that too...
I'm not claiming that you can take Lisp, throw out all
its macro facilities, also throw out everything in it
that's currently defined using macros, and have a good
language at the end. (You can't.) I'm not claiming that
macros aren't needed. (They are.) So I'm not sure what's
supposed to be wrong with the above. It's not even as if
the use I made of LOOP does anything that would be very
painful with only more primitive looping constructs.
(So what *am* I saying? Just that Anton's examples of
CASE and COND aren't terribly good ones to make his
point.)
--
Gareth McCaughan
.sig under construc
Gareth McCaughan wrote:
> (So what *am* I saying? Just that Anton's examples of
> CASE and COND aren't terribly good ones to make his
> point.)
I agree, mostly. The example came up because the OP mentioned Smalltalk,
and the issue of CASE in Smalltalk is well-known, for reasons (at least some
of them) that are related to the question at hand.
Also, CASE and COND still illustrate the basic problems: if you decide you
can live with the limited syntax options, then there's a performance issue
which requires a good inlining compiler to solve, keeping in mind that one
of the major ways *in practice* to guarantee that your compiler inlines
something is to use a macro; or there's syntactic messiness that arises if
you try to eliminate the performance issue another way, as with Rob's
suggestion.
So as I see it, the important points are inherent even in my weak example.
However, the keen sensibilities of Lispers are such that it's not possible
to get away with a weak example even if it supports their own prejudices!
;)
Anton
Gareth McCaughan wrote:
> I agree with much of what you're saying, but it's entirely possible
> to do a very decent "functional" COND and CASE in CL with bearable
> syntax.
OK, I agree, assuming the compiler efficiency caveat (addressed below). I
should rather have picked a macro which does binding of variables in
addition to other things. I was trying not to resort to heavy weaponry,
like LOOP.
But I think your answer is an interesting meta-comment on the original
question: you use macros to define syntax to illustrate the syntax which is
being considered as an alternative to macros. You couldn't do that the
other way around, which is an important point in this case. You also use
LOOP - which of course, you could easily do without here, but my point is
that both of these things are indicative of "what macros have done for us
lately".
> Given some way of communicating to the compiler that KOND and KASE
> should always be inlined and that the loops inside them should always
> be fully unrolled when possible, I don't see any reason why they
> shouldn't end up producing pretty much the exact same code as we
> get from a real COND or CASE.
You're right. A sufficiently advanced compiler should be able to do that.
Hey, although it's not actually my favorite way to do it, one way you could
communicate that a function should be fully inlined is to implement it as a
macro...
Anton
"Anton van Straaten" <·····@appsolutions.com> writes:
> But I think your answer is an interesting meta-comment on the original
> question: you use macros to define syntax to illustrate the syntax which is
> being considered as an alternative to macros. You couldn't do that the
> other way around, which is an important point in this case. You also use
> LOOP - which of course, you could easily do without here, but my point is
> that both of these things are indicative of "what macros have done for us
> lately".
Oh, certainly; I'm an enormous fan of macros, and I think they're
one of the biggest wins Lisp has to offer. I was just picking nits
with your choice of examples :-).
> > Given some way of communicating to the compiler that KOND and KASE
> > should always be inlined and that the loops inside them should always
> > be fully unrolled when possible, I don't see any reason why they
> > shouldn't end up producing pretty much the exact same code as we
> > get from a real COND or CASE.
>
> You're right. A sufficiently advanced compiler should be able to do that.
More than that, I'm fairly sure some actually available compilers
do such things, so I'm not just saying "here's a piece of magic
that ought in principle to be possible".
> Hey, although it's not actually my favorite way to do it, one way you could
> communicate that a function should be fully inlined is to implement it as a
> macro...
:-)
--
Gareth McCaughan
.sig under construc
Anton van Straaten <·····@appsolutions.com> wrote:
+---------------
| To get a feel for the issue, try writing CASE or COND as an ordinary
| function in Lisp and see what you end up with. It's not just about the
| delaying required for each branch, it's also how you make the matching
| happen without requiring a lot of syntax repeated over and over for every
| branch. A naive attempt might look like (using backslash as pseudocode for
| a concise lambda):
|
| (cond expr
| (list (\ x match-expr1) (\ action-expr2))
| (list (\ x match-expr2) (\ action-expr2))
| ...)
...
| Next, think about performance. Since COND is now a function, when an
| expression like the above evaluates, it involves evaluating n*2 lambdas
| where n is the number of branches. This creates n*2 procedures every time
| the COND is executed...
+---------------
Well, one can handle that by making COND take exactly *three* thunks
as arguments: a test, an action, and a single "else" continuation.
Hmmm... That's really a "functional IF" (fif?), which, using Garath's
brackets for thunks, one could write as follows [deliberately using
"bad" indenting to avoid the drifting-to-the-right problem]:
(fif
[boolean-expr-1] [action-expr-1]
[(fif
[boolean-expr-2] [action-expr-2]
[(fif
[boolean-expr-2] [action-expr-2]
[(fif
[boolean-expr-2] [action-expr-2]
[otherwise-action])])])])
Oooh... That looks ugly, doesn't it? ;-}
Still, it addresses the performance issue, since while the lamdba for
the second FIF always needs to be executed (yielding a closure), the
lambdas inside it don't if the first test succeeds.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
Rob Warnock wrote:
> Well, one can handle that by making COND take exactly *three* thunks
> as arguments: a test, an action, and a single "else" continuation.
> Hmmm... That's really a "functional IF" (fif?), which, using Garath's
> brackets for thunks, one could write as follows [deliberately using
> "bad" indenting to avoid the drifting-to-the-right problem]:
[SNIP]
Credit (or debit) where it's due: I stole the [...] syntax
from Smalltalk. For all I know, Smalltalk may have stolen it
from somewhere else.
--
Gareth McCaughan
.sig under construc
Russell Wallace wrote:
> If LAMBDA had a shorter spelling, would macros still be needed?
Beware of "Isn't this all we need?" questions. They give you Turing
Machines.
Pascal
--
ECOOP 2004 Workshops - Oslo, Norway
*1st European Lisp and Scheme Workshop, June 13*
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
*2nd Post-Java Workshop, June 14*
http://prog.vub.ac.be/~wdmeuter/PostJava04/
Pascal Costanza <········@web.de> wrote in message news:<············@f1node01.rhrz.uni-bonn.de>...
> Russell Wallace wrote:
>
> > If LAMBDA had a shorter spelling, would macros still be needed?
>
> Beware of "Isn't this all we need?" questions. They give you Turing
> Machines.
I have always held that humans are simply Turing Machines with
torn sprocket holes on the paper tape.
On 8705 day of my life Russell Wallace wrote:
> But are there practical examples of macros that could not be expressed
> as higher-order functions even if LAMBDA was short enough that you
> didn't mind typing it on every call?
For example, DEFTYPEL and TYPEL macros from my TypeL package
(http://lispnik.newmail.ru/typel). TypeL is subset of Lisp with
polymorphic type inference and type-checking (a-la ML).
--
Ivan Boldyrev
Assembly of a Japanese bicycle requires greatest peace of spirit.
On Tue, 06 Apr 2004 10:42:46 +0700, Ivan Boldyrev
<···············@cgitftp.uiggm.nsc.ru> wrote:
>For example, DEFTYPEL and TYPEL macros from my TypeL package
>(http://lispnik.newmail.ru/typel). TypeL is subset of Lisp with
>polymorphic type inference and type-checking (a-la ML).
Thanks!
Here's another question that's occurred to me: Given that macros are
needed, should they be in the same namespace as functions, or a
different namespace? I know the analogous debate for functions and
_variables_ has been done to death with a bit of necrophilia thrown
in, but I don't recall having seen it for functions and macros - are
there, for example, any situations where you'd want a function and
macro with the same name?
--
"Sore wa himitsu desu."
To reply by email, remove
the small snack from address.
http://www.esatclear.ie/~rwallace
Russell Wallace <················@eircom.net> wrote:
+---------------
| Given that macros are needed, should they be in the same namespace
| as functions, or a different namespace?
+---------------
Same, because they go in the same position (first) in a compound form.
+---------------
| ...are there, for example, any situations where you'd want a function
| and macro with the same name?
+---------------
Well, compiler macros. But CL already does "the right thing" in that case.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607