Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-26 Thread Greg Ewing
Michael Chermside wrote:
I've been following this conversation, and it sounds to me as if we
are stumbling about in the dark, trying to feel our way toward something
very useful and powerful. I think Jim is right, what we're feeling our
way toward is macros.
I considered saying something like that about 3 posts ago,
but I was afraid of getting stoned for heresy...
  ... Eventually, there would
  develop a large number of different Python dialects (as some
  claim has happened in the Lisp community) each dependent on macros
  the others lack. The most important casualty would be Python's
  great *readability*.

In other words, rather than hearing what we'd like to be able to DO
with blocks, I'd like to hear what we want to PROHIBIT DOING with
blocks.
From that quote, it would seem what we want to do is prohibit
anything that would make code less readable. Or prohibit
anything that would permit creating a new dialect. Or something.
--
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[EMAIL PROTECTED]  +--+
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-26 Thread Greg Ewing
Michael Chermside wrote:
if the answer is that we want to prohibit nothing, then the right
solution is macros.
I'm not sure about that. Smalltalk manages to provide very
reasonable-looking user-defined control structures without
using compile-time macros, just normal runtime evaluation
together with block arguments. It does this by starting
out with a fairly minimal and very flexible syntax.
This raises the question of why people feel the need for
macros in Lisp or Scheme, which have an even more minimal
and flexible syntax. I think part of the reason is that
the syntax for passing an unevaluated block is too obtrusive.
In Scheme you can define a function (not macro) that is
used like this:
  (with-file foo/blarg
 (lambda (f)
(do-something-with f)))
But there is a natural tendency to want to be able to
cut out the lambda cruft and just write something like:
  (with-file foo/blarg (f)
 (do-something-with f))
and for that you need a macro.
The equivalent in Smalltalk would be something like
  File open: foo/blarg do: [:f f something]
which doesn't look too bad (compared to the rest of
the language!) because the block-passing syntax is
fairly unobtrusive.
So in summary, I don't think you necessarily *need*
macros to get nice-looking user-defined control structures.
It depends on other features of the language.
--
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[EMAIL PROTECTED]  +--+
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-26 Thread Rodrigo Dias Arruda Senra
[ Michael Walter ]:
 A couple of examples out of my tired head (solely from a user perspective) :-)
 
 Embedding domain specific language (ex.: state machine):
 ...
 
 Embedding domain specific language (ex.: markup language):
 ...
 
 Embedding domain-specific language (ex.: badly-designed database table):
 ...

 ..., which might actually prove someone's point that the
 language designer shouldn't allow people to do such things.

 The whole macros issue comes to a tradeoff between
 power+expressiviness X readability. 

 IMVHO, macros are readability assassins. The power (for any developer)
 to introduce new syntax is *not* a desirable feature, but something
 to be avoided. And that alone should be a stronger argument than
 a hundred use cases. 

 cheers,
 Senra

-- 
Rodrigo Senra 
--
MSc Computer Engineerrodsenra(at)gpr.com.br  
GPr Sistemas Ltdahttp://www.gpr.com.br/ 
Personal Blog http://rodsenra.blogspot.com/

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] defmacro (was: Anonymous blocks)

2005-04-26 Thread Jim Jewett
  (3)  Add macros.  We still have to figure out how to limit their
obfuscation.

  nobody has given even a *remotely*
  plausible mechanism for how exactly you would get code executed at
  compile time.
 
 macros can (and *possibly* should) be evaluated at run-time.

 We must still have very different views on what a macro is.

In a compiled language, it is (necessarily) compiled.  In an interpreted
language, it doesn't have to be.

 After a macros is run, there is new syntax that needs to be parsed 
 and compiled to bytecode.   ... anything that requires invoking the
 compiler each time a macro is used will be so slow that nobody will
 want to use it.

I had been thinking that the typical use would be during function (or
class) definition.  The overhead would be similar to that of decorators,
and confined mostly to module loading.

I do see your point that putting a macro call inside a function could be
slow -- but I'm not sure that is a reason to forbid it.

 Even if the macros just rerun the same boilerplate code less efficiently,
 it is still good to have that boilerplate defined once, instead of cutting
 and pasting.  Or, at least, it is better *if* that once doesn't become
 unreadable in the process.

 I am unable to assess the value of this mechanism unless you make a
 concrete proposal. You seem to have something in mind but you're not
 doing a good job getting it into mine...

I'm not confident that macros are even a good idea; I just don't want
a series of half-macros.  That said, here is a strawman.

defmacro boiler1(name, rejects):
def %(name) (*args):
for a in args:
if a in %(rejects):
print Don't send me %s % a
...
boiler1(novowels, aeiouy)
boiler2(nokey5, jkl)

I'm pretty sure that a real version should accept suites instead of just
arguments, and the variable portion might even be limited to suites 
(as in the thunk discussion).  It might even be reasonable to mark
macro calls as different from function calls.

template novowels from boiler1(aeiou):
suite

but I can't help thinking that multiple suites should be possible, and
then they should be named, and ... that spurred at least one 
objection.  http://mail.python.org/pipermail/python-dev/2005-April/052949.html

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-26 Thread Greg Ewing
Jim Jewett wrote:
I had been thinking that the typical use would be during function (or
class) definition.  The overhead would be similar to that of decorators,
and confined mostly to module loading.
But that's too late, unless you want to resort to bytecode
hacking. By the time the module is loaded, its source code
has long since been compiled into code objects.
--
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[EMAIL PROTECTED]  +--+
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Michael Chermside
Jim Jewett writes:
 As best I can tell, the anonymous blocks are used to take
 care of boilerplate code without changing the scope -- exactly
 what macros are used for.

Folks, I think that Jim is onto something here.

I've been following this conversation, and it sounds to me as if we
are stumbling about in the dark, trying to feel our way toward something
very useful and powerful. I think Jim is right, what we're feeling our
way toward is macros.

The problem, of course, is that Guido (and others!) are on record as
being opposed to adding macros to Python. (Even good macros... think
lisp, not cpp.) I am not quite sure that I am convinced by the argument,
but let me see if I can present it:

  Allowing macros in Python would enable individual programmers or
  groups to easily invent their own syntax. Eventually, there would
  develop a large number of different Python dialects (as some
  claim has happened in the Lisp community) each dependent on macros
  the others lack. The most important casualty would be Python's
  great *readability*.

(If this is a strawman argument, i.e. if you know of a better reason
for keeping macros OUT of Python please speak up. Like I said, I've
never been completely convinced of it myself.)

I think it would be useful if we approached it like this: either what
we want is the full power of macros (in which case the syntax we choose
should be guided by that choice), or we want LESS than the full power
of macros. If we want less, then HOW less?

In other words, rather than hearing what we'd like to be able to DO
with blocks, I'd like to hear what we want to PROHIBIT DOING with
blocks. I think this might be a fruitful way of thinking about the
problem which might make it easier to evaluate syntax suggestions. And
if the answer is that we want to prohibit nothing, then the right
solution is macros.

-- Michael Chermside

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Shane Holloway (IEEE)
Michael Chermside wrote:
Jim Jewett writes:
As best I can tell, the anonymous blocks are used to take
care of boilerplate code without changing the scope -- exactly
what macros are used for.

Folks, I think that Jim is onto something here.
I've been following this conversation, and it sounds to me as if we
are stumbling about in the dark, trying to feel our way toward something
very useful and powerful. I think Jim is right, what we're feeling our
way toward is macros.
I am very excited about the discussion of blocks.  I think they can 
potentially address two things that are sticky to express in python 
right now.  The first is to compress the common try/finally use cases 
around resource usage as with files and database commits.  The second is 
language extensibility, which makes us think of what macros did for Lisp.

Language extensibility has two motivations.  First and foremost is to 
allow the programmer to express his or her *intent*.  The second 
motivation is to reuse code and thereby increase productivity.  Since 
methods already allow us to reuse code, our motivation is to increase 
expressivity.  What blocks offer is to make Python's suites something a 
programmer can work with.  Much like using a metaclass putting control 
of class details into the programmer's hands.  Or decorators allowing us 
to modify method semantics.  If the uses of decorators tells us 
anything, I'm pretty sure there are more potential uses of blocks than 
we could shake many sticks at.  ;)

So, the question comes back to what are blocks in the language 
extensibility case?  To me, they would be something very like a code 
object returned from the compile method.  To this we would need to 
attach the globals and locals where the block was from.  Then we could 
use the normal exec statement to invoke the block whenever needed. 
Perhaps we could add a new mode 'block' to allow the ControlFlow 
exceptions mentioned elsewhere in the thread.  We still need to find a 
way to pass arguments to the block so we are not tempted to insert them 
in locals and have them magically appear in the namespace.  ;) 
Personally, I'm rather attached to as (x, y): introducing the block.

To conclude, I mocked up some potential examples for your entertainment.  ;)
Thanks for your time and consideration!
-Shane Holloway

Interfaces::
def interface(interfaceName, *bases, ***aBlockSuite):
blockGlobals = aBlockSuite.globals().copy()
blockGlobals.update(aBlockSuite.locals())
blockLocals = {}
exec aBlock in blockGlobals, blockLocals
return iterfaceType(interfaceName, bases, blockLocals)
IFoo = interface('IFoo'):
def isFoo(self): pass
IBar = interface('IBar'):
def isBar(self): pass
IBaz = interface('IBaz', IFoo, IBar):
def isBaz(self): pass
Event Suites::
def eventSinksFor(events, ***aBlockSuite):
blockGlobals = aBlockSuite.globals().copy()
blockGlobals.update(aBlockSuite.locals())
blockLocals = {}
exec aBlock in blockGlobals, blockLocals
for name, value in blockLocals.iteritems():
if aBlockSuite.locals().get(name) is value:
continue
if callable(value):
events.addEventFor(name, value)
def debugScene(scene):
eventSinksFor(scene.events):
def onMove(pos):
print pos:, pos
def onButton(which, state):
print button:, which, state
def onKey(which, state):
print key:, which, state
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Aahz
On Mon, Apr 25, 2005, Shane Holloway (IEEE) wrote:

 Interfaces::
 
 def interface(interfaceName, *bases, ***aBlockSuite):
 blockGlobals = aBlockSuite.globals().copy()
 blockGlobals.update(aBlockSuite.locals())
 blockLocals = {}
 
 exec aBlock in blockGlobals, blockLocals
 
 return iterfaceType(interfaceName, bases, blockLocals)
 
 IFoo = interface('IFoo'):
 def isFoo(self): pass

Where does ``aBlock`` come from?
-- 
Aahz ([EMAIL PROTECTED])   * http://www.pythoncraft.com/

It's 106 miles to Chicago.  We have a full tank of gas, a half-pack of
cigarettes, it's dark, and we're wearing sunglasses.  Hit it.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Jim Jewett
Guido:

 My problem with macros is actually more practical: Python's compiler
 is too dumb. I am assuming that we want to be able to import macros
 from other modules, and I am assuming that macros are expanded by the
 compiler, not at run time; but the compiler doesn't follow imports ...

Expanding at run-time is less efficient, but it works at least as well
semantically.  If today's alternative is manual cut-n-paste, I would 
still rather have the computer do it for me, to avoid accidental forks.

It could also be done (though not as cleanly) by making macros act as
import hooks.  

import defmacro# Stop processing until defmacro is loaded.
 # All future lines will be
preprocessed by the
 # hook collection
...
from defmacro import foo   # installs a foo hook, good for the rest of the file

Michael Chermside:
 I think it would be useful if we approached it like this: either what
 we want is the full power of macros (in which case the syntax we choose
 should be guided by that choice), or we want LESS than the full power
 of macros. If we want less, then HOW less?

 In other words, rather than hearing what we'd like to be able to DO
 with blocks, I'd like to hear what we want to PROHIBIT DOING with
 blocks. I think this might be a fruitful way of thinking about the
 problem which might make it easier to evaluate syntax suggestions. And
 if the answer is that we want to prohibit nothing, then the right
 solution is macros.

 I'm personally at a loss understanding your question here. Perhaps you
 could try answering it for yourself?

Why not just introduce macros?  If the answer is We should, it is just 
hard to code, then use a good syntax for macros.  If the answer is
We don't want 

xx sss (S\!   2k3 ]

to ever be meaningful, then we need to figure out exactly what to 
prohibit.  Lisp macros are (generally, excluding read macros) limited 
to taking and generating complete S-expressions.  If that isn't enough
to enforce readability, then limiting blocks to expressions (or even
statements) probably isn't enough in python.

Do we want to limit the changing part (the anonymous block) to
only a single suite?  That does work well with the yield syntax, but it
seems like an arbitrary restriction unless *all* we want are resource 
wrappers.

Or do we really just want a way to say that a function should share its
local namespace with it's caller or callee?  In that case, maybe the answer
is a lexical or same_namespace keyword.  Or maybe just a recipe to make
exec or eval do the right thing.

def myresource(rcname, callback, *args):
rc=open(rcname)
same_namespace callback(*args)
close(rc)

def process(*args):
...

...
if __name__ == '__main__':
 myresource(file1, process, arg1, arg2)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Michael Chermside
Guido writes:
 My problem with macros is actually more practical: Python's compiler
 is too dumb. I am assuming that we want to be able to import macros
 from other modules, and I am assuming that macros are expanded by the
 compiler, not at run time; but the compiler doesn't follow imports
 (that happens at run time) so there's no mechanism to tell the
 compiler about the new syntax. And macros that don't introduce new
 syntax don't seem very interesting (compared to what we can do
 already).

That's good to hear. It expresses fairly clearly what the challenges
are in implementing macros for Python, and expressing the challenges
makes it easier to attack the problem. My interest comes because some
recent syntax changes (generators, generator expressions) have seemed
to me like true language changes, but others (decorators, anonymous-blocks)
to me just cry out this would be easy as a macro!.



I wrote:
 I think it would be useful if we approached it like this: either what
 we want is the full power of macros (in which case the syntax we choose
 should be guided by that choice), or we want LESS than the full power
 of macros. If we want less, then HOW less?

 In other words, rather than hearing what we'd like to be able to DO
 with blocks, I'd like to hear what we want to PROHIBIT DOING with
 blocks. I think this might be a fruitful way of thinking about the
 problem which might make it easier to evaluate syntax suggestions. And
 if the answer is that we want to prohibit nothing, then the right
 solution is macros.

Guido replied:
 I'm personally at a loss understanding your question here. Perhaps you
 could try answering it for yourself?

You guys just think too fast for me. When I started this email, I replied
Fair enough. One possibility is But while I was trying to condense
my thoughts down from 1.5 pages to something short and coherent (it takes
time to write it short) everything I was thinking became obscelete as
both Paul Moore and Jim Jewett did exactly the kind of thinking I was
hoping to inspire:

Paul:
 What I feel is the key concept here is that of injecting code into a
 template form (try...finally, or try..except..else, or whatever)
  [...]
 Specifically, cases where functions aren't enough. If I try to
 characterise precisely what those cases are, all I can come up with is
 when the code being injected needs to run in the current scope, not
 in the scope of a template function. Is that right?

Jim:
 Why not just introduce macros?  If the answer is We should, it is just
 hard to code, then use a good syntax for macros.  If the answer is
 We don't want
   xx sss (S\!   2k3 ]
 to ever be meaningful, then we need to figure out exactly what to
 prohibit.
 [...]
 Do we want to limit the changing part (the anonymous block) to
 only a single suite?  That does work well with the yield syntax, but it
 seems like an arbitrary restriction unless *all* we want are resource
 wrappers.

 Or do we really just want a way to say that a function should share its
 local namespace with it's caller or callee?  In that case, maybe the answer
 is a lexical or same_namespace keyword.

My own opinion is that we DO want macros. I prefer a language have a few,
powerful constructs rather than lots of specialized ones. (Yet I still
believe that doing different things should look different... which is
why I prefer Python to Lisp.) I think that macros could solve a LOT of
problems.

There are lots of things one might want to replace within macros, from
identifiers to punctuation, but I'd be willing to live with just two of
them: expressions, and series-of-statements (that's almost the same as
a block). There are only two places I'd want to be able to USE a macro:
where an expression is called for, and where a series-of-statements is
called for. In both cases, I'd be happy with a function-call like syntax
for including the macro.

Well, that's a lot of wanting... now I all I need to do is invent a
clever syntax that allows these in an elegant fashion while also solving
Guido's point about imports (hint: the answer is that it ALL happens at
runtime). I'll go think some while you guys zoom past me again. wink

-- Michael Chermside

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Shane Hathaway
Robert Brewer wrote:
 So currently, all subclasses just override __set__, which leads to a
 *lot* of duplication of code. If I could write the base class' __set__
 to call macros like this:
 
 def __set__(self, unit, value):
 self.begin()
 if self.coerce:
 value = self.coerce(unit, value)
 oldvalue = unit._properties[self.key]
 if oldvalue != value:
 self.pre()
 unit._properties[self.key] = value
 self.post()
 self.end()
 
 defmacro begin:
 pass
 
 defmacro pre:
 pass
 
 defmacro post:
 pass
 
 defmacro end:
 pass

Here is a way to write that using anonymous blocks:

def __set__(self, unit, value):
with self.setting(unit, value):
if self.coerce:
value = self.coerce(unit, value)
oldvalue = unit._properties[self.key]
if oldvalue != value:
with self.changing(oldvalue, value):
unit._properties[self.key] = value

def setting(self, unit, value):
# begin code goes here
yield None
# end code goes here

def changing(self, oldvalue, newvalue):
# pre code goes here
yield None
# post code goes here


 ...(which would require macro-blocks which were decidedly *not*
 anonymous) then I could more cleanly write a subclass with additional
 macro methods:
 
 defmacro pre:
 old_children = self.children()
 
 defmacro post:
 for child in self.children:
 if child not in old_children:
 notify_somebody(New child %s % child)

def changing(self, oldvalue, newvalue):
old_children = self.children()
yield None
for child in self.children:
if child not in old_children:
notify_somebody(New child %s % child)

Which do you prefer?  I like fewer methods. ;-)

Shane
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Robert Brewer
Shane Hathaway wrote:
 Robert Brewer wrote:
  So currently, all subclasses just override __set__, which leads to a
  *lot* of duplication of code. If I could write the base 
 class' __set__
  to call macros like this:
  
  def __set__(self, unit, value):
  self.begin()
  if self.coerce:
  value = self.coerce(unit, value)
  oldvalue = unit._properties[self.key]
  if oldvalue != value:
  self.pre()
  unit._properties[self.key] = value
  self.post()
  self.end()
  
  defmacro begin:
  pass
  
  defmacro pre:
  pass
  
  defmacro post:
  pass
  
  defmacro end:
  pass
 
 Here is a way to write that using anonymous blocks:
 
 def __set__(self, unit, value):
 with self.setting(unit, value):
 if self.coerce:
 value = self.coerce(unit, value)
 oldvalue = unit._properties[self.key]
 if oldvalue != value:
 with self.changing(oldvalue, value):
 unit._properties[self.key] = value
 
 def setting(self, unit, value):
   # begin code goes here
 yield None
 # end code goes here
 
 def changing(self, oldvalue, newvalue):
 # pre code goes here
 yield None
 # post code goes here
 
...
 Which do you prefer?  I like fewer methods. ;-)

I still prefer more methods, because my actual use-cases are more
complicated. Your solution would work for the specific case I gave, but
try factoring in:

* A subclass which needs to share locals between begin and post, instead
of pre and post.

or

* A set of 10 subclasses which need the same begin() but different end()
code.

Yielding seems both too restrictive and too inside-out to be readable,
IMO.


Robert Brewer
MIS
Amor Ministries
[EMAIL PROTECTED]
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Jim Jewett
On 4/25/05, Guido van Rossum [EMAIL PROTECTED] wrote:
  It could also be done (though not as cleanly) by making macros act as
  import hooks.

 Brrr. What about imports that aren't at the top level (e.g. inside a 
 function)?

Bad style already.  :D
If you want to use the macro, you have to ensure it was already imported.

That said, I did say it wasn't as clean; think of it like pre-caching which 
dictionary that resolved an attribute lookup.  Don't start with the complexity, 
but consider not making the optimization impossible.
 
  Why not just introduce macros?

 Because I've been using Python for 15 years without needing them?

And also without anonymous blocks or generator finalizers or resource
managers.

 Sorry, but why not add feature X is exactly what we're trying to
 AVOID here.

If anything is added, it might be better to add a single generalized tool 
instead of several special cases -- unless the tool is so general as to be 
hazardous.  Unlimited macros are that hazardous.

   If the answer is We don't want
 
  xx sss (S\!   2k3 ]
 
  to ever be meaningful, then we need to figure out exactly what to
  prohibit.  

 I don't understand what the point is of using an example like
 xx sss (S\! 2k3 ].

The simplest way to implement macros is to add an import hook 
that can modify (replace) the string containing the source code.  
Unfortunately, that would allow rules like 

replace any line starting with 'xx' with the number 7  

Outside of obfuscators, almost no one would do something quite so 
painful as that ... but some people would start using regex 
substitutions or monkey-patching.  I would hate to debug code that
fails because a standard library module is secretly changed (on load, 
not on disk where I can grep for it) by another module, which doesn't 
even mention that library by name...

As Michael said, we have to think about what transformations we 
do not want happening out of sight.  I would have said Just use
it responsibly if I hadn't considered pathological cases like that one.

 [yield works great for a single anonymous block, but not so 
  great for several blocks per macro/template.]

 Pehaps you've missed some context here? Nobody seems to be able to
 come up with other [than resource wrappers] use cases, that's why 
 yield is so attractive.

Sorry; to me it seemed obvious that you would occasionally want to 
interleave the macro/template and the variable portion.  Robert Brewer 
has since provided good examples at

http://mail.python.org/pipermail/python-dev/2005-April/052923.html
http://mail.python.org/pipermail/python-dev/2005-April/052924.html

  Or do we really just want a way to say that a function should share its
  local namespace with it's caller or callee?  In that case, maybe the answer
  is a lexical or same_namespace keyword.  Or maybe just a recipe to make
  exec or eval do the right thing.

 But should the same_namespace modifier be part of the call site or
 part of the callee? 

IMHO, it should be part of the calling site, because it is the calling site
that could be surprised to find its own locals modified.  The callee 
presumably runs through a complete call before it has a chance to
be surprised.  

I did leave the decision open because I'm not certain that mention-in-caller
wouldn't end up contorting a common code style.  (It effectively forces
the macro to be in control, and the meaningful code to be callbacks.)

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Guido van Rossum
It seems that what you call macros is really an unlimited
preprocessor. I'm even less interested in that topic than in macros,
and I haven't seen anything here to change my mind.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Shane Hathaway
Robert Brewer wrote:
 I still prefer more methods, because my actual use-cases are more
 complicated. Your solution would work for the specific case I gave, but
 try factoring in:
 
 * A subclass which needs to share locals between begin and post, instead
 of pre and post.
 
 or
 
 * A set of 10 subclasses which need the same begin() but different end()
 code.
 
 Yielding seems both too restrictive and too inside-out to be readable,
 IMO.

Ok, that makes sense.  However, one of your examples seemingly pulls a
name, 'old_children', out of nowhere.  That's hard to fix.  One of the
greatest features of Python is the simple name scoping; we can't lose that.

Shane
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] defmacro (was: Anonymous blocks)

2005-04-25 Thread Samuele Pedroni
Robert Brewer wrote:
Shane Hathaway wrote:
Robert Brewer wrote:
So currently, all subclasses just override __set__, which leads to a
*lot* of duplication of code. If I could write the base 
class' __set__
to call macros like this:
   def __set__(self, unit, value):
   self.begin()
   if self.coerce:
   value = self.coerce(unit, value)
   oldvalue = unit._properties[self.key]
   if oldvalue != value:
   self.pre()
   unit._properties[self.key] = value
   self.post()
   self.end()
   defmacro begin:
   pass
   
   defmacro pre:
   pass
   
   defmacro post:
   pass
   
   defmacro end:
   pass
Here is a way to write that using anonymous blocks:
   def __set__(self, unit, value):
   with self.setting(unit, value):
   if self.coerce:
   value = self.coerce(unit, value)
   oldvalue = unit._properties[self.key]
   if oldvalue != value:
   with self.changing(oldvalue, value):
   unit._properties[self.key] = value
   def setting(self, unit, value):
# begin code goes here
   yield None
   # end code goes here
   def changing(self, oldvalue, newvalue):
   # pre code goes here
   yield None
   # post code goes here
...
Which do you prefer?  I like fewer methods. ;-)

I still prefer more methods, because my actual use-cases are more
complicated. Your solution would work for the specific case I gave, but
try factoring in:
* A subclass which needs to share locals between begin and post, instead
of pre and post.
or
* A set of 10 subclasses which need the same begin() but different end()
code.
Yielding seems both too restrictive and too inside-out to be readable,
IMO.

it seems what you are asking for are functions that are evaluated in 
namespace of the caller:

- this seems fragile, the only safe wat to implement 'begin' etc is to 
exactly know what goes on in __set__ and what names are used there

- if you throw in deferred evaluation for exprs or suites passed in
as arguments and even without considering that, it seems pretty horrid 
implementation-wise

Notice that even in Common Lisp you cannot really do this, you could 
define a macro that produce a definition for __set__ and takes fragments 
corresponding to begin ... etc


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] defmacro (was: Anonymous blocks)

2005-04-23 Thread Jim Jewett
As best I can tell, the anonymous blocks are used to take 
care of boilerplate code without changing the scope -- exactly 
what macros are used for.  The only difference I see is that in 
this case, the macros are limited to entire (possibly compound) 
statements.  

To make this more concrete,

Guido:
 in synchronized(the_lock):
 BODY

Nick Coghlan:
 s/in/with/ to get PEP 310.
...

Guido's recent screed crystallised the idea of writing resources
 as two-part generators:
...

[Adding Reinhold Birkenfeld's suggestion of a blank yield]

 def my_resource():
print Hi! # Do entrance code
yield   # Go on with the contents of the 'with' block
print Bye!# Do exit code

The macro itself looks reasonable -- so long as there is only 
ever one changing block inside the macro.  I'm not sure that 
is a reasonable restriction, but the alternative is ugly enough 
that maybe passing around locals() starts to be just as good.

What about a block that indicates the enclosed namespaces
will collapse a level?

defmacro myresource(filename):
make explicit calls to named callback functions, but 
  within the same locals() scope.

with myresource(thefile):
def reader(): 
...
def writer():
...
def fn():


Then myresource, reader, writer, and fn would share a
namespace without having to manually pass it around.

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com