Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > For Kenny Tilton: Why do I need macros revisited.

Reply
Thread Tools

For Kenny Tilton: Why do I need macros revisited.

 
 
Chris Reedy
Guest
Posts: n/a
 
      08-21-2003
For everyone -

Apologies for the length of this message. If you don't want to look
at the long example, you can skip to the end of the message.

And for the Python gurus among you, if you can spare the time, I
would appreciate any comments (including words like evil and disgusting,
if you think they are applicable :-}) on the example here.

Kenny -

I asked my question about macros with some malice aforethought. This
is a topic I've thought about in the past.

> Andrew Dalke wrote:
>
>> Kenny Tilton:
>>
>>> This macro:
>>>
>>> (defmacro c? (&body code)
>>> `(let ((cache :unbound))
>>> (lambda (self)
>>> (declare (ignorable self))
>>> (if (eq cache :unbound)
>>> (setf cache (progn ,@code))
>>> cache))))

>>
>>
>>
>> I have about no idea of what that means. Could you explain
>> without using syntax? My guess is that it caches function calls,
>> based only on the variable names. Why is a macro needed
>> for that?


I sympathize with Andrew on this. I had to study this and the following
code for awhile before I figured out what you are doing. However, I do
have an advantage, I know lisp and the macro system and just how
powerful the macro system is.

> (defun get-cell (self slotname) ;; this fn does not need duplicating
> (let ((sv (slot-value self slotname)))
> (typecase sv
> (function (funcall sv self))
> (otherwise sv))))
>
> (defmethod right ((self box)) ;; this needs duplicating for each slot
> (get-cell box right))
>
> But I just hide it all (and much more) in:
>
> (defmodel box ()
> ((left :initarg :left :accessor left)
> (right :initarg :right :accessor right)))
>
> ....using another macro:
>
> (defmacro defmodel (class superclasses (&rest slots))
> `(progn
> (defclass ,class ,superclasses
> ,slots)
> ,@(mapcar (lambda (slot)
> (destructuring-bind
> (slotname &key initarg accessor)
> slot
> (declare (ignore slotname initarg))
> `(defmethod ,accessor ((self ,class))
> (get-cell self ',slotname))))
> slots)))


Ok. The following is more lines of code than you have here. On the other
hand, I think it does about the same thing:

<Example>

class cellvalue(object):
def __init__(self):
self._fn = None
def _get_value(self, obj):
if hasattr(self, '_value'):
return self._value
else:
value = self._fn
if callable(self._fn):
value = value(obj)
self._value = value
return value
def _set_value(self, value):
self._value = value
def _del_value(self):
del self._value
def _set_fn(self, fn):
self._fn = fn
if hasattr(self, '_value'):
self._del_value()

class modelproperty(object):
def _init_cell(self, obj):
obj.__dict__[self.name] = cellvalue()
def __get__(self, obj, cls):
if obj is None:
return self
else:
return obj.__dict__[self.name]._get_value(obj)
def __set__(self, obj, val):
obj.__dict__[self.name]._set_value(val)
def __delete__(self, obj):
obj.__dict__[self.name]._del_value()
def setfn(self, obj, fn):
obj.__dict__[self.name]._set_fn(fn)
def setname(self, name):
self.name = name
self.__doc__ = 'Model Property '+str(name)

class modeltype(type):
def __init__(cls, name, bases, dict):
super(modeltype, cls).__init__(name, bases, dict)
modelprops = []
for attr, decl in dict.items():
if isinstance(decl, modelproperty):
decl.setname(attr)
modelprops.append(attr)
if modelprops:
__originit = getattr(cls, '__init__')
def _modeltype_init(self, *args, **kw):
for attr in modelprops:
getattr(self.__class__, attr)._init_cell(self)
if __originit is not None:
__originit(self, *args, **kw)
setattr(cls, '__init__', _modeltype_init)

>>> class foo:

.... __metaclass__ = modeltype
.... x = modelproperty()
.... def __init__(self, x=None):
.... self.__class__.x.setfn(self, x)
>>> z = foo(x=lambda self: self.a + 2)
>>> z.a = 5
>>> print z.x

7
>>> z.x = -3
>>> print z.x

-3
>>> z.a = 15
>>> print z.x

-3
>>> del z.x
>>> print z.x

17

I think that has most of the behavior you were looking for. As you can
see from the example, I leaned (I'm not sure leaned is a strong enough
work ) on the newer capabilities for metaclasses and descriptors.
(And learned a lot about exactly how they work by writing this up!)

</Example>

Having looked at the two pieces of code, the only thing that struck me
about how they're used is that the lambda expression needed in the
Python version is clunkier than the version in the Lisp version. On the
other hand, that might be addressed by a somewhat more elegant syntax in
Python for constant code blocks, something that's been mentioned by
others in recent messages.

Even though the Python setup (with two classes and a metaclass) is
longer than the Lisp version, I'm not sure it's any clunkier or harder
to understand.

So back to my original question, why do I want macros in Python?

Let me provide a candidate answer and rebuttal:

The real reason I want to do macros in Lisp is that they allow me to
easily write new custom languages. Would a sufficiently powerful macro
facility in Python allow me to do this? I suspect that the answer to
this question would only be yes if that included some sort of parser
generator facility.

Expanding on that: One of the nice things about Python (at least for
those like me who like the language) is the clean syntax. However, that
comes at a price: Needing a real parser to parse the language.

Lisp on the other hand has an extremely simple syntax that doesn't
require a real parser. That allows me to create whole new "syntaxes" in
lisp, since I'm not really changing the syntax, just changing how a
given set of S-expressions are interpreted.

On the other hand, if I'm going to go to the complexity of including a
parser generator so I can generate my own custom languages, it sounds to
me like I'm about to reproduce what the Perl/Parrot people are up to. (I
admit that I'd really like the time to look at what they're doing more
deeply.)

Which brings me back to my original question: Would a macro facility in
Python really buy me anything? And, in view of Alex's arguments, would
that benefit outweigh the potential significant costs in other areas?

Chris



-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
 
Reply With Quote
 
 
 
 
Kenny Tilton
Guest
Posts: n/a
 
      08-22-2003


Chris Reedy wrote:
> For everyone -
>
> Apologies for the length of this message. If you don't want to look at
> the long example, you can skip to the end of the message.
>
> And for the Python gurus among you, if you can spare the time, I would
> appreciate any comments (including words like evil and disgusting, if
> you think they are applicable :-}) on the example here.
>
> Kenny -
>
> I asked my question about macros with some malice aforethought. This
> is a topic I've thought about in the past.
>
>> Andrew Dalke wrote:
>>
>>> Kenny Tilton:
>>>
>>>> This macro:
>>>>
>>>> (defmacro c? (&body code)
>>>> `(let ((cache :unbound))
>>>> (lambda (self)
>>>> (declare (ignorable self))
>>>> (if (eq cache :unbound)
>>>> (setf cache (progn ,@code))
>>>> cache))))
>>>
>>>
>>>
>>>
>>> I have about no idea of what that means. Could you explain
>>> without using syntax? My guess is that it caches function calls,
>>> based only on the variable names. Why is a macro needed
>>> for that?

>>

>
> I sympathize with Andrew on this. I had to study this and the following
> code for awhile before I figured out what you are doing. However, I do
> have an advantage, I know lisp and the macro system and just how
> powerful the macro system is.
>
>> (defun get-cell (self slotname) ;; this fn does not need duplicating
>> (let ((sv (slot-value self slotname)))
>> (typecase sv
>> (function (funcall sv self))
>> (otherwise sv))))
>>
>> (defmethod right ((self box)) ;; this needs duplicating for each slot
>> (get-cell box right))
>>
>> But I just hide it all (and much more) in:
>>
>> (defmodel box ()
>> ((left :initarg :left :accessor left)
>> (right :initarg :right :accessor right)))
>>
>> ....using another macro:
>>
>> (defmacro defmodel (class superclasses (&rest slots))
>> `(progn
>> (defclass ,class ,superclasses
>> ,slots)
>> ,@(mapcar (lambda (slot)
>> (destructuring-bind
>> (slotname &key initarg accessor)
>> slot
>> (declare (ignore slotname initarg))
>> `(defmethod ,accessor ((self ,class))
>> (get-cell self ',slotname))))
>> slots)))

>
>
> Ok. The following is more lines of code than you have here. On the other
> hand, I think it does about the same thing:
>
> <Example>
>
> class cellvalue(object):
> def __init__(self):
> self._fn = None
> def _get_value(self, obj):
> if hasattr(self, '_value'):
> return self._value
> else:
> value = self._fn
> if callable(self._fn):
> value = value(obj)
> self._value = value
> return value
> def _set_value(self, value):
> self._value = value
> def _del_value(self):
> del self._value
> def _set_fn(self, fn):
> self._fn = fn
> if hasattr(self, '_value'):
> self._del_value()
>
> class modelproperty(object):
> def _init_cell(self, obj):
> obj.__dict__[self.name] = cellvalue()
> def __get__(self, obj, cls):
> if obj is None:
> return self
> else:
> return obj.__dict__[self.name]._get_value(obj)
> def __set__(self, obj, val):
> obj.__dict__[self.name]._set_value(val)
> def __delete__(self, obj):
> obj.__dict__[self.name]._del_value()
> def setfn(self, obj, fn):
> obj.__dict__[self.name]._set_fn(fn)
> def setname(self, name):
> self.name = name
> self.__doc__ = 'Model Property '+str(name)
>
> class modeltype(type):
> def __init__(cls, name, bases, dict):
> super(modeltype, cls).__init__(name, bases, dict)
> modelprops = []
> for attr, decl in dict.items():
> if isinstance(decl, modelproperty):
> decl.setname(attr)
> modelprops.append(attr)
> if modelprops:
> __originit = getattr(cls, '__init__')
> def _modeltype_init(self, *args, **kw):
> for attr in modelprops:
> getattr(self.__class__, attr)._init_cell(self)
> if __originit is not None:
> __originit(self, *args, **kw)
> setattr(cls, '__init__', _modeltype_init)
>
> >>> class foo:

> ... __metaclass__ = modeltype
> ... x = modelproperty()
> ... def __init__(self, x=None):
> ... self.__class__.x.setfn(self, x)
> >>> z = foo(x=lambda self: self.a + 2)
> >>> z.a = 5
> >>> print z.x

> 7
> >>> z.x = -3
> >>> print z.x

> -3
> >>> z.a = 15
> >>> print z.x

> -3
> >>> del z.x
> >>> print z.x

> 17
>
> I think that has most of the behavior you were looking for. As you can
> see from the example, I leaned (I'm not sure leaned is a strong enough
> work ) on the newer capabilities for metaclasses and descriptors.
> (And learned a lot about exactly how they work by writing this up!)


<g> looks a lot like the code I was writing when I began a Python port
of my Cells project. I'll be open-sourcing the Lisp version soon, you
can do the Python port.

You are absolutely right. Metaclasses are killer. I am surprised
Pythonistas afraid of macros let them into the language! I actually had
a metaclass implementation of Cells until I decided to release the
source. The MOP is not part of the standard, and it shows across
implementations. Hell, MCL does not even expose a MOP.

>
> </Example>
>
> Having looked at the two pieces of code, the only thing that struck me
> about how they're used is that the lambda expression needed in the
> Python version is clunkier than the version in the Lisp version.


You will be delighted to know that one of Lisp priesthood sees no need
for macros since what they do can be done with lambdas. Not sure if that
is so where one is generating multiple top-level forms from one clause.
Me, I like hiding implementation details as mush as possible, and having
just one place to go when changing how something works.

As for the lambda being clunkier, un-hunh, and if you decide to change
the mechanism after a lot of them have been coded, perhaps passing a
second argument, here comes the mega-edit. Worse, what happens when the
toy hack reaches maturity and you get the final version of the macro:

this:
(c? (+ 10 (left self)))

expands to:
(make-c-dependent
:code '((+ 10 (left self)))
:rule (lambda (c &aux (self (c-model c)))
(+ 10 (left self))))

One funny thing is that even if one open codes that, the readers you all
are so worried about still do not know what C-DEPENDENT is.

Now picture a make-instance with five of those in a row. The text widget
font is a function of a user preference, all four dimensions are a
function of the font size and string length, the color may be a function
of sysntax judgment for highlighting, etc etc. Now you cannot see the
semantics for all the redundant, essentially meaningless wiring.

> So back to my original question, why do I want macros in Python?


Hiding the wiring, where a function will not do because the argument is
your source code.

>
> Let me provide a candidate answer and rebuttal:
>
> The real reason I want to do macros in Lisp is that they allow me to
> easily write new custom languages.


No, that is not a big reason. It is cool that one could do that readily
if one stuck to the basic sexpr notation, but my experience to date is
that I do not need a wholly new language as long as I can drop into new
syntax (c?...) periodically to get what I would have created in a wholly
new embedded language.

> Which brings me back to my original question: Would a macro facility in
> Python really buy me anything? And, in view of Alex's arguments, would
> that benefit outweigh the potential significant costs in other areas?


Lispniks have not seen code become unreadable because of macros. That is
something you all (well, most) are imagining. You are almost positing it
as given. And it is simply not so. We have pointed out again and again
that macros are no harder to understand than functions or classes, but
no one addresses that point. Some say "I want to see all the legal
Pythion instructions". Except when it is in a function, I guess.
Strangely, quite a few of you have also conceded macros can leverage a
language.

Well, it seems like we have covered everything pretty thoroughly. Back
to RoboCup!

--

kenny tilton
clinisys, inc
http://www.tilton-technology.com/
---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
-- Bob Uecker

 
Reply With Quote
 
 
 
 
Jacek Generowicz
Guest
Posts: n/a
 
      08-22-2003
"Andrew Dalke" <> writes:

> http://www.schemers.org/Documents/St...-3.html#%_sec_
> Temp_4
> ] As Scheme became more widespread, local dialects began to
> ] diverge until students and researchers occasionally found it difficult
> ] to understand code written at other sites.


That has probably more to do with the fact that Scheme is
minimalistic. And if you have a minimalistic langugage, you end up
having to implement a lot of utilities before you can get on with what
you are actulally trying to achieve (or have your language
implementation provide them as extensions).

Schemers criticize Common Lisp for being too big. The consequence of
having a big language (a la CL, not a la C++) is that most things that
"everybody" needs are already in the language. In Scheme "everybody"
ends up re-inventing the things that "everybody" needs, separately,
leading to fragmentation. In CL, everybody agrees on how to implement
the things that "everybody" needs: you use the ones defined by the
standard. In this way, any macro-magic is restricted to the domain
specific corners of your application.

In summary, I reckon that any inter-Scheme incomprehensibility or
Scheme fragmentation results from starting with a language that
doesn't offer enough out of the box.
 
Reply With Quote
 
Paul Foley
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 08:09:40 GMT, Andrew Dalke wrote:

>> Lispniks have not seen code become unreadable because of macros. That is
>> something you all (well, most) are imagining. You are almost positing it
>> as given. And it is simply not so.


> Terry Reedy pointed out something from some Scheme documentation
> found by Dave Kuhlman:
> http://www.schemers.org/Documents/St...-3.html#%_sec_
> Temp_4
> ] As Scheme became more widespread, local dialects began to
> ] diverge until students and researchers occasionally found it difficult
> ] to understand code written at other sites.


> I cannot say if that's because of macros or other aspects of Scheme.


Scheme, as such, is barely a language. It's pretty useless on its own.
Most of the functionality of an actual Scheme /implementation/ is
extra-standard stuff (i.e., not Scheme), which, naturally enough,
every implementor does differently.

[Scheme didn't even have macros until R4RS (1991?), and then only as
an appendix...]

>> We have pointed out again and again
>> that macros are no harder to understand than functions or classes, but
>> no one addresses that point.


> What about Terry's comment, based on the above URL:
> ) Reading the third referenced page on Macros, I notice that the amount
> ) of syntax definition for the macro sublanguage is as large as a
> ) substantial portion (one-third?) of that for core Python (if condensed
> ) to the same density). So, just by definitional bulk, having it in the
> ) language would not be a free ride.


Scheme macros are not the same as Lisp macros. Scheme macros are a
lot more complicated (and less useful; but most Scheme implementations
also offer Lisp-style macros...)


--
Just because we Lisp programmers are better than everyone else is no
excuse for us to be arrogant. -- Erann Gat

(setq reply-to
(concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      08-22-2003

"Paul Foley" <> wrote in message
news:...
> Scheme, as such, is barely a language. It's pretty useless on its

own.
> Most of the functionality of an actual Scheme /implementation/ is
> extra-standard stuff (i.e., not Scheme), which, naturally enough,
> every implementor does differently.


Core Python, while useful on it own, is also pretty sparse. So I
gather it would be something like having multiple Python
implementations (of comparable popularity) with different sets of
builtins and overlapping but incompatible 'standard' libraries. The
Python community is fortunate to have avoided that.

....
> Scheme macros are not the same as Lisp macros. Scheme macros are a
> lot more complicated (and less useful; but most Scheme

implementations
> also offer Lisp-style macros...)


Please excuse my confusing of Scheme with Lisp. I am pleased to find
that my difficulty in reading the Scheme macro stuff wasn't just me.
But note that there have been proposals that if Python were to have a
macro facility, it should be 'hygenic', which I presume means like
Scheme macros.

Until some advocate of a Python macro facility adds more detail to the
proposal beyound 'Lisp/Scheme-like maco facility', it is really hard
for someone like me, who has used neither, to have much of any
concrete idea of what is being proposed.

Terry J. Reedy


 
Reply With Quote
 
David Mertz
Guest
Posts: n/a
 
      08-22-2003
"Andrew Dalke" <> wrote previously:
|I've seen David Mertz' xml_pickle code which makes good use of
|[metaclasses], but don't yet follow how it works.

I'm afraid I must insist here that the use of metaclasses in
gnosis.xml.pickle is utterly trivial, and just for show. You'll
have to look elsewhere for "good use" of them .

Yours, David...

--
mertz@ _/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY: \_\_\_\_ n o
gnosis _/_/ Postmodern Enterprises \_\_
..cx _/_/ \_\_ d o
_/_/_/ IN A WORLD W/O WALLS, THERE WOULD BE NO GATES \_\_\_ z e


 
Reply With Quote
 
Kenny Tilton
Guest
Posts: n/a
 
      08-22-2003


Andrew Dalke wrote:
> Kenny Tilton:
>
>>We have pointed out again and again
>>that macros are no harder to understand than functions or classes, but
>>no one addresses that point.

>
>
> What about Terry's comment, based on the above URL:
> ) Reading the third referenced page on Macros, I notice that the amount
> ) of syntax definition for the macro sublanguage is as large as a
> ) substantial portion (one-third?) of that for core Python (if condensed
> ) to the same density). So, just by definitional bulk, having it in the
> ) language would not be a free ride.


Oy. This comment is about understanding how to write macros. We are
talking about whether:

(with-open-file (f "my.data" <...options...>)
(do-fun-things-with f))

....is harder to understand than:

(open-file-and-do "my.data"
<...options...>
:do-this (lambda (f) (do-fun-things-with f)))

btw, /writing/ macros takes a while to learn, or it did for me anyway,
because one has moved to a different space than a programmer normally
occupies, somewhere inside the compiler you might say. So some of the
time you are typing in code for run-time and some of the time you are
typing in code that runs at compile time to produce the code that runs
at runtime. And there's some weird syntax, with backquotes and coomas
and ampersands. Great fun, once it is second nature, but till then...the
neat thing is realizing you can put in debug statements that execute
while the macro is being expanded, not at run time. And you can have a
bug in the expanding code such that evaluating the form dies before it
begins being evaluated! <g>

>
>
>>Strangely, quite a few of you have also conceded macros can leverage a
>>language.

>
>
> Leverage a language ... for what? And for whom?


The keystone macro of the RoboCup client I plan to share with soccer
hooligans everywhere is DEFTASK:

(deftask <taskname> &key achieved subtasks wait-on-subtasks?
attempt retry-when)

achieved is a rule for deciding when the task has been achieved.

subtasks are subtasks to be completed (achieved) before the task at hand
is attempted, unless...

wait-on-subtasks? is nil, in which case the task can decide on its won
when to check if it has alreadt been achieved (you'll need an example).

attempt is code which generates a command to the soccer server,
hopefully leading to task achievement

retry-when tells the engine when to try again if not yet achieved. eg,
don't turn again to look for the ball until we have gotten a new "see"
message.

Now that's pretty slim doc, but there will be more and examples galore
(and an on-line help desk <g>), but some points:

No, no one looking at my code has ever seen deftask before. But if they
have done any lisp at all, they will know I have built a little task
solving engine for them. They will know because I used standard Lisp
terminology, the "def" prefix. They will understand all the keywords,
but immediately scream for documentation because keywords do not a
user's guide make. They will also see that the style is declarative,
which is meant to be helpful (and is) but they will sweat bullets until
they have a solid feel for how the engine works inside ("why did a
completed subtask start getting solved again"). I'll have to come clean
on the guts of the engine.

Or, as some of the folks on our team have done, they can macroexpand any
deftask form. They can look at the source of deftask as well, but that
can be harder because the final output is kinda disguised by all the
code which builds the final output. Once they see the astonishing
output, they will likely decide just to have me provide a functional
spec so they do not have to worry about the engine internals. Like I do.

They just write:

(deftask head-for-ball () ;; literally set body heading for ball
()
:achieved (bwhen (ball (^ball))
(< (+ .neck. (seen-dir ball)) 10))
:subtasks (list (mktask find-ball))
:attempt (bwhen (ball (^ball))
(let ((correction (+ .neck. (seen-dir ball))))
(ptrc nil "correcting" correction) ;;debug macro!
`(turn ,correction))))

The unadvertised synatx above (the two () forms near the beginning, are
a giveaway that deftask expands into the familiar (to lispniks) defclass
form. ie, deftask is implemented as defclass. Again, I make an effort to
keep the syntax lispy and recognizable and familiar and all that good
stuff. They can add slots to their task, have supertasks, etc etc.

So the defclass power is /leveraged/ to make deftask even better than i
could make it. Generic functions automatically can be dispatched by
soccer task, without me lifting a finger.

In the end, a bunch of people with just an interest in machine learning
and genetic algorithms and soccer can have some fun concnetrating just
on the ML and GA and football. Because I am providing a task-executing
"language" which deals with the soccer server for them.

As for what the above would look like without macros:

(defmodel head-for-ball (task)
()
(:default-initargs
:wait-on-subtasks-p t
:kids (c? (let ((task self) (self (player self)))
(mapcar (lambda (subtask)
(if (symbolp subtask)
(make-instance subtask layer self)
subtask))
(thekids (list (mktask find-ball))))))
:achieved-body (lambda (cells::c &aux (task (cells::c-model
cells::c)) (self (player task)))
(declare (ignorable self task))
(bwhen (ball (^ball))
(< (+ .neck. (seen-dir ball)) 10)))
:retry-when-body (lambda (cells::c &aux (task (cells::c-model
cells::c)) (self (player task)))
(declare (ignorable cells::c self task))
nil)
:attempt-body (lambda (cells::c &aux (task (cells::c-model
cells::c)) (self (player task)))
(declare (ignorable self task))
(bwhen (ball (^ball))
(let ((correction (+ .neck. (seen-dir ball))))
(ptrc nil "head-for-ball correcting" correction)
`(turn ,correction))))))

Not too bad, but then you have to expand defmodel.

--

kenny tilton
clinisys, inc
http://www.tilton-technology.com/
---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
-- Bob Uecker

 
Reply With Quote
 
Jacek Generowicz
Guest
Posts: n/a
 
      08-22-2003
"Terry Reedy" <> writes:

> Until some advocate of a Python macro facility adds more detail to the
> proposal beyound 'Lisp/Scheme-like maco facility', it is really hard
> for someone like me, who has used neither, to have much of any
> concrete idea of what is being proposed.


Until some advocate of a Python macro facility adds more detail to the
proposal ... it is really hard for me to have much of any concrete
idea what is being proposed ... because Lisp-style macros rely on the
fact that Lisp code is expressed in a fundamental Lisp data structure,
in the form of its parse tree. This ain't the case in Python, so the
whole macro business suddenly gets more complicated by an order of
magnitude or two.

I just can't imagine what such a macro system would look like. Maybe
someone with deep knowledge of Dylan can enlighten us.
 
Reply With Quote
 
David Mertz
Guest
Posts: n/a
 
      08-22-2003
"Andrew Dalke" <> wrote previously:
|I've seen David Mertz' xml_pickle code which makes good use of
|[metaclasses], but don't yet follow how it works.

I'm afraid I must insist here that the use of metaclasses in
gnosis.xml.pickle is utterly trivial, and just for show. You'll
have to look elsewhere for "good use" of them .

Yours, David...

--
mertz@ _/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY: \_\_\_\_ n o
gnosis _/_/ Postmodern Enterprises \_\_
..cx _/_/ \_\_ d o
_/_/_/ IN A WORLD W/O WALLS, THERE WOULD BE NO GATES \_\_\_ z e


 
Reply With Quote
 
Michele Simionato
Guest
Posts: n/a
 
      08-23-2003
Kenny Tilton <> wrote in message news:<>...
> You are absolutely right. Metaclasses are killer. I am surprised
> Pythonistas afraid of macros let them into the language!


Me too. Actually they are quite *scaring*. In my post on
"PEP 312 (and thus 30 implemented with a black magic trick" actually
I argued that they were much *worse* than macros, since they are able
to change the *semantics* of the language, a much more dangerous
thing than simply changing the syntax. In a sense, they are deeply
unpythonic,
the exact opposite of "explicit is better than implicit".
Maybe it enters in "practicality beats purity", but this is stretching
the principle quite a bit. Same for descriptors and properties, which
still are much less dangerous.
I think metaclasses were intended not to be used, except from
developers
and very advanced users. The problem is that once you have a feature
in
a language, people will use it. I do like metaclasses, but I would be
scared
in debugging a large program written by others using them and with
poor ocumentation. Each time you see a class, you are never sure of
what it is
doing; when the bug happens, you are not sure if it is in the class or
in
the metaclass (this happened to me even with my own programs).
It is quite worrysome, actually. Fortunately, we are good people, here
on c.l.py, and I don't think anybody would mess things up, but it
could
*easily* be done.
Now, I trust the programmer and I do like the power and the freedom;
but still it strikes to me as a case of multiple personality to have
a language that at the surface is plain, clear, nicely indented, and
under the cover ... caveat emptor!

Let it be this way, anyway, and let us continue to advertise it as
a "clean" language. Let us stop people who want case statement, repeat
... until, ternary operators, braces, and the like, and let us under
the cover give people the freedom to program classes and altering at
will nearly everything at the semantics level. Let the other worry
about syntax ...




> I actually had
> a metaclass implementation of Cells until I decided to release the
> source. The MOP is not part of the standard, and it shows across
> implementations. Hell, MCL does not even expose a MOP.
>


Quite impressive. You are actually saying that you do prefer Python
over
Lisp on a problem of ultra-high level programming which should be
the rightful Lisp playhouse ... To be fair, the reason is not lack of
power by Lisp, but lack of standardization, still it is something that
makes me thinking ...

Michele Simionato, Ph. D.

http://www.phyast.pitt.edu/~micheles
--- Currently looking for a job ---
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
Explanation of macros; Haskell macros mike420@ziplip.com Python 80 11-07-2003 02:22 AM
Re: Explanation of macros; Haskell macros Michael T. Babcock Python 0 11-03-2003 01:54 PM
Re: Explanation of macros; Haskell macros mike420@ziplip.com Python 5 11-01-2003 01:09 AM
Re: Explanation of macros; Haskell macros mike420@ziplip.com Python 1 10-07-2003 04:07 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57