macro FAQ

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrew Dalke

    macro FAQ

    Here's a proposed Q&A for the FAQ based on a couple recent
    threads. Appropriate comments appreciated

    X.Y: Why doesn't Python have macros like in Lisp or Scheme?

    Before answering that, a clarification on what 'macro' means.
    A Lisp macro is a way of modifying code when that code is first
    defined. It can rearrange the structure of the code, and add and
    remove parts of it. Unlike C's #define macro language, Lisp
    macros understand the structure of the expression and the
    context (or "closure") in which it is found.

    Here's a simple example of what a macro might do for Python.
    A complaint about Python is that constructors for simple data
    types require typing the parameter names three times, as in

    class Country:
    def __init__(self, name, capitol):
    self.name = name
    self.capitol = capitol

    Suppose you could create a new way to create functions, which
    looked at the argument list and automatically set the corresponding
    member. This would let you replace the above with something
    more like

    class Country:
    def __init__(self, name, capitol) [arg_assign]:
    pass

    where the 'arg_assign' would use the function definition
    and code to make a new function used in place of the
    existing one and with the 'self.name = name' and
    'self.capitol = capitol' code automatically added to
    the front of the code.

    This is a very powerful technique and especially nice for
    high-performance code where the macro can optimize
    code before it is actually evaluated. Macros work well in
    Lisp or Scheme, where the code is the data, all written
    pretty much as a parse tree.

    The first problem with implementing a macro system in Python
    is coming up with a readable syntax; that is, how it's "spelled."
    The example shown above, using the [] after the function
    definition, was taken from a proposed syntax for adding
    function modifiers like 'staticmethod' and 'classmethod' to
    Python.

    The second problem is that Python's code blocks do not
    store the original parse tree, so there's nothing to manipulate.
    If you use 'dir()' or the inspect module you'll see some fields
    like the list of argument names and the default value to use
    for the fields. Nowhere will you find the original parse tree.
    (The C implementation of Python does give access to the
    Python byte code, but this is not part of the language
    specification and Java implementation doesn't support it.)

    These problems can be resolved, and Dylan shows that
    an infix-based/Algol-like language can support macros
    similar to those used in Lisp.

    The deeper question is, should Python include macros?

    People with a Lisp background might have a problem
    understanding this viewpoint. Macros add flexibility, and
    more flexibilty lets programmers be more productive; or
    so the argument goes.

    Those against including macros in Python point out that
    Python has a different focus. It has a broad target audience.
    Beginners can pick it up pretty easily yet advanced
    developers also enjoy working in the language. New features,
    like new builtin functions, additional core types, expanding
    the standard libraries, list comprensions, metaclasses and
    deriving from object, and macros, all make it harder to
    learn how to use Python well and shifts the balance more
    towards advanced programmers.

    More importantly, the detractors -- including those
    with plenty of experience using macros in Lisp -- argue that
    macros cause dialects to form. Macros can modify other code to
    make it fit the problem better, while functions only use other
    code but make no modifications. This makes them very
    powerful but means that understanding a section of code
    requires also knowing about any macros which might use the
    code. In an extreme case which wouldn't be used in real
    projects, every * could be replaced with a +.

    (As an aside, some proponents argue that macros and
    functions are essentially the same. Alex Martelli made
    an interesting observation about one difference: it's often
    worthwhile to turn a set of code into a function even if it
    is only called from one place, because it helps simplify
    the code into smaller chucks which are easier to understand.
    Macros, on the other hand, should almost never be used
    unless they are used many times.)

    With only one or a small group of people working together
    on a project there is little problem. Macros help in developing
    idioms specific to the problem and group. When groups
    share code, they also share idioms, and anyone who has had
    to deal with UK vs. US English knows the effect idioms have
    in mututal understanding.

    Those against macros say their benefits do not outweigh
    the likelihood that the Python community will be broken up
    into distinct subsets, where people from one group find it
    hard to use code from another.

    The proponents for macros say this has not been a problem
    in Lisp. Macros are misused, but so are functions and classes.
    The same community feedback which encourages people to
    use proper coding styles also encourages people to use macros
    correctly. Those against reassert that not only can it be a
    problem but it's happened to them personally.

    At this point the discussion usually breaks down, with the
    Lispers pulling out the old canard about Python (and every
    other language) being a half-complete, poor reimplementatio n
    of Lisp, while Pythonistas trot out the expression "Lisp is like
    a ball of mud. You can add any amount of mud to it and it
    still looks like a ball of mud."

    Those interested in actual language improvements then ask for
    concrete examples of how macros might be used for Python.
    So far, the examples given are ones which could equally well
    be done in Python using metaclasses, properties, and other
    existing mechanisms. For example, the arg_assign example
    given above could, I think, be done with a modified__new__ .

    The problem at this point seems to be that the two languages
    have different enough object models and accepted best
    practices that it's hard for an intuition based on Lisp to
    know immediately how to apply that intuition to Python.

    If you want to encourage Python to have macros, you must
    therefore propose a syntax for it and give solid examples of
    what the result would look like when applied to real Python
    code. Simply stating that macros are needed is not good
    enough nor are examples showing how macros are useful
    for Lisp code. (Besides, believe it or not but some of us
    don't know enough Lisp to follow your examples ;)

    In the meanwhile, if you want to experiment with manipulating
    code trees, you can use decompyle to turn byte code back
    into Python source and the compiler module to turn source into
    an AST and thence into byte code.

    Andrew Dalke
    dalke@dalkescie ntific.com


  • Michele Simionato

    #2
    Re: macro FAQ

    "Andrew Dalke" <adalke@mindspr ing.com> wrote in message news:<Dsz1b.340 9$Ej6.113@newsr ead4.news.pas.e arthlink.net>.. .[color=blue]
    > Here's a proposed Q&A for the FAQ based on a couple recent
    > threads. Appropriate comments appreciated
    >
    > X.Y: Why doesn't Python have macros like in Lisp or Scheme?[/color]

    This is all very interesting and I do agree that there shouuld be a
    FAQ about macros, nevertheless I don't see your message as suitable
    for a FAQ. It is ways too verbose. I mean, if one asks for a macro,
    s/he already knows what a macro is. The FAQ should be much
    shorter. What you wrote is more useful and interesting for
    Pythonistas than from Lispers.
    I think your document should be made available on the Web somewhere,
    but not in the FAQ. Of course the FAQ could and should give a pointer
    to it. Maybe lispers would be helped from a page describing how
    some of the things made in macros in Lisp can be made in Python.
    This page should be referred in the FAQ too. It is clear, however,
    that many things involving macros cannot just be done in Python
    (I mean, unless implementing a custom macro interpreter in Python,
    which actually I wrote few months ago as a proof of concept (google
    on c.l.py for simionato macros, first hit) and which I DO NOT use ;).

    Michele Simionato, Ph. D.
    MicheleSimionat o@libero.it

    --- Currently looking for a job ---

    Comment

    • Michele Simionato

      #3
      Re: macro FAQ

      "Andrew Dalke" <adalke@mindspr ing.com> wrote in message news:<Dsz1b.340 9$Ej6.113@newsr ead4.news.pas.e arthlink.net>.. .[color=blue]
      > Here's a proposed Q&A for the FAQ based on a couple recent
      > threads. Appropriate comments appreciated
      >
      > X.Y: Why doesn't Python have macros like in Lisp or Scheme?[/color]

      This is all very interesting and I do agree that there shouuld be a
      FAQ about macros, nevertheless I don't see your message as suitable
      for a FAQ. It is ways too verbose. I mean, if one asks for a macro,
      s/he already knows what a macro is. The FAQ should be much
      shorter. What you wrote is more useful and interesting for
      Pythonistas than from Lispers.
      I think your document should be made available on the Web somewhere,
      but not in the FAQ. Of course the FAQ could and should give a pointer
      to it. Maybe lispers would be helped from a page describing how
      some of the things made in macros in Lisp can be made in Python.
      This page should be referred in the FAQ too. It is clear, however,
      that many things involving macros cannot just be done in Python
      (I mean, unless implementing a custom macro interpreter in Python,
      which actually I wrote few months ago as a proof of concept (google
      on c.l.py for simionato macros, first hit) and which I DO NOT use ;).

      Michele Simionato, Ph. D.
      MicheleSimionat o@libero.it

      --- Currently looking for a job ---

      Comment

      • John J. Lee

        #4
        Re: macro FAQ

        mis6@pitt.edu (Michele Simionato) writes:
        [color=blue]
        > "Andrew Dalke" <adalke@mindspr ing.com> wrote in message news:<Dsz1b.340 9$Ej6.113@newsr ead4.news.pas.e arthlink.net>.. .[color=green]
        > > Here's a proposed Q&A for the FAQ based on a couple recent
        > > threads. Appropriate comments appreciated
        > >
        > > X.Y: Why doesn't Python have macros like in Lisp or Scheme?[/color][/color]
        [...][color=blue]
        > I think your document should be made available on the Web somewhere,
        > but not in the FAQ. Of course the FAQ could and should give a pointer
        > to it.[/color]
        [...]

        +1, FWIW


        John

        Comment

        • John J. Lee

          #5
          Re: macro FAQ

          mis6@pitt.edu (Michele Simionato) writes:
          [color=blue]
          > "Andrew Dalke" <adalke@mindspr ing.com> wrote in message news:<Dsz1b.340 9$Ej6.113@newsr ead4.news.pas.e arthlink.net>.. .[color=green]
          > > Here's a proposed Q&A for the FAQ based on a couple recent
          > > threads. Appropriate comments appreciated
          > >
          > > X.Y: Why doesn't Python have macros like in Lisp or Scheme?[/color][/color]
          [...][color=blue]
          > I think your document should be made available on the Web somewhere,
          > but not in the FAQ. Of course the FAQ could and should give a pointer
          > to it.[/color]
          [...]

          +1, FWIW


          John

          Comment

          • John J. Lee

            #6
            Re: macro FAQ

            "Andrew Dalke" <adalke@mindspr ing.com> writes:
            [color=blue]
            > Here's a proposed Q&A for the FAQ based on a couple recent
            > threads. Appropriate comments appreciated[/color]
            [...][color=blue]
            > Those against including macros in Python point out that
            > Python has a different focus. It has a broad target audience.
            > Beginners can pick it up pretty easily yet advanced
            > developers also enjoy working in the language. New features,
            > like new builtin functions, additional core types, expanding
            > the standard libraries, list comprensions, metaclasses and
            > deriving from object, and macros, all make it harder to
            > learn how to use Python well and shifts the balance more
            > towards advanced programmers.
            >
            > More importantly, the detractors -- including those
            > with plenty of experience using macros in Lisp -- argue that
            > macros cause dialects to form. Macros can modify other code to
            > make it fit the problem better, while functions only use other
            > code but make no modifications. This makes them very
            > powerful but means that understanding a section of code
            > requires also knowing about any macros which might use the
            > code. In an extreme case which wouldn't be used in real
            > projects, every * could be replaced with a +.[/color]
            [...]

            About the first paragraph here: I don't recall anyone arguing that,
            but maybe I forget. Anyway, my problem with it is that it reinforces
            the "Python is a scripting language for amateurs, not suitable for
            large scale / systems programming" attitude. I think Python
            demonstrates that there isn't much tension in reality between the
            'advanced programmers' and the beginners -- both seem to want a simple
            language. And as you say, the argument about dialects is more
            important anyway.

            Other than that, excellent stuff.


            John

            Comment

            • John J. Lee

              #7
              Re: macro FAQ

              "Andrew Dalke" <adalke@mindspr ing.com> writes:
              [color=blue]
              > Here's a proposed Q&A for the FAQ based on a couple recent
              > threads. Appropriate comments appreciated[/color]
              [...][color=blue]
              > Those against including macros in Python point out that
              > Python has a different focus. It has a broad target audience.
              > Beginners can pick it up pretty easily yet advanced
              > developers also enjoy working in the language. New features,
              > like new builtin functions, additional core types, expanding
              > the standard libraries, list comprensions, metaclasses and
              > deriving from object, and macros, all make it harder to
              > learn how to use Python well and shifts the balance more
              > towards advanced programmers.
              >
              > More importantly, the detractors -- including those
              > with plenty of experience using macros in Lisp -- argue that
              > macros cause dialects to form. Macros can modify other code to
              > make it fit the problem better, while functions only use other
              > code but make no modifications. This makes them very
              > powerful but means that understanding a section of code
              > requires also knowing about any macros which might use the
              > code. In an extreme case which wouldn't be used in real
              > projects, every * could be replaced with a +.[/color]
              [...]

              About the first paragraph here: I don't recall anyone arguing that,
              but maybe I forget. Anyway, my problem with it is that it reinforces
              the "Python is a scripting language for amateurs, not suitable for
              large scale / systems programming" attitude. I think Python
              demonstrates that there isn't much tension in reality between the
              'advanced programmers' and the beginners -- both seem to want a simple
              language. And as you say, the argument about dialects is more
              important anyway.

              Other than that, excellent stuff.


              John

              Comment

              • Doug Tolton

                #8
                Re: macro FAQ

                Jacek Generowicz <jacek.generowi cz@cern.ch> wrote in message news:<tyfbruf99 8w.fsf@lxplus01 4.cern.ch>...[color=blue][color=green]
                > > Macros can modify other code to make it fit the problem better,[/color]
                >
                > What do you mean by "other" code? Macros modify the code that is
                > passed to them as an argument, transforming it before the compiler
                > gets to see it. I get the impression that you believe that macros can
                > somehow modify code from other parts of the program. They can't.
                >
                > Ultimately, macros just save you a lot of typing of source code. (And
                > thereby save you a lot of bugs.) If you can't type it as soure code,
                > then a macro can't do it.
                >[color=green]
                > > while functions only use other code but make no modifications.[/color]
                >
                > This only strengthens the above suspicion, but I'm not really sure
                > what you mean, here.
                >[color=green]
                > > This makes them very powerful but means that understanding a section
                > > of code requires also knowing about any macros which might use the
                > > code.[/color]
                >
                > What do you mean by "macros using code" ?
                >
                > The macros are part of the code, just like functions are. To
                > understand the code, you must understand what the macros and functions
                > do.
                >[color=green]
                > > In an extreme case which wouldn't be used in real projects, every *
                > > could be replaced with a +.[/color]
                >
                > This almost completely convinces me that you are very confused about
                > what macros can achieve.
                >
                > Either, you are suggesting that one might write a macro which replaces
                > every * operator with a + operator, and then pass _the entire source
                > code_ of a project to it (possible, but patently absurd); or you are
                > suggesting that it is possible to write a macro "over here" which,
                > somehow, surreptitiously modifies existing source code "over there".
                >
                > a) Macros cannot do the latter.
                >
                > b) You can achieve something very similar in Python, by re-binding
                > attributes of __builtins__.
                >
                > Think of the point of macros in another way. The point is _not_ to
                > take existing source code, and to change it. The point is to take
                > something that is not (necessarily) valid source code, and turn it
                > into valid source code, before the compiler gets to see it. Why?
                > Because this allows you to create a shorthand notation, and use macros
                > to expand it to real code. Think in terms of encoding design patterns.
                >[/color]

                I think Jacek has made an extremely good point here, and I want to
                follow up on it to determine if everyone has a clear understanding of
                what macros are and are not. Following I have outlined a series of
                questions an answers to attempt to illuminate the issue. Please
                suggest any clarifications or distinctions that need to be made. Also
                note that the examples presented are purposefully trivial and could in
                many instances be accomplished other ways, however I am presenting
                these examples in order to provide a meaningful context to proceed
                from.

                Question: What are Macros?

                Answer: Macros are an advanced templating system that allow dynamic
                evaluation of code during run time. Essentially Macros allow you to
                pass in some variables that are then expanded into valid Python syntax
                which is then executed.

                Question: Can't I accomplish this same functionality via string
                parsing and eval?

                Answer: Eval will accept any valid Python expression and execute it.
                This is however regarded by many as a security hole. Macros allow
                this type of expressiveness while limiting many of the security risks.
                With a Macro you can more specifically control what types of actions
                are permissible.

                Question: I have some existing modules, if I import a macro from
                someone else, could the macro make my existing code perform in
                unexpected ways?

                Answer: No. A macro doesn't modify existing code, in order to invoke
                a macro it must be called just like a function call. So a Macro
                couldn't alter the functionality of existing code any more than a
                function could. The only way to accomplish such a feat would be to
                manually open each file and parse through them and re-evaluate them.
                This type of functionality is not what macros are about any more than
                a function call would be.

                Question: How would Macros work in practice?

                Answer: Here is a trivial example macro to start with:

                def HelloFunc(messa ge):
                print "%s\n" % (message)

                defmacro uselessmacro(me ssage):
                macroexpansion = "HelloFunc( %s)" % (message)

                defmacro callfunc(funcna me, message):
                macroexpansion = """
                calllog = open("/var/log/functions.log", "a")
                calllog.write(" %(funcname)s was called.\n")
                calllog.flush()
                calllog.close()
                %(funcname)s(%( message)s)
                """ % locals()

                if __name__ == "__main__":
                uselessmacro("H ello World")
                callfunc("Hello Func", "Hello World")

                # Note, Jacek's method of using indentation is an interesting
                alternative to calling them as a
                # function.

                # Second note, this textarea box does not have a compiler, so please
                forgive any syntax errors :)

                uselessmacro simply passes it's arguments through to HelloFunc
                undisturbed
                callfunc logs all calls to a function before evaluating the function

                You could clearly accomplish this functionality using other means,
                however I have used such a trivial example in order to illustrate
                several points:

                1) Macros once they are defined would most likely be invoked the same
                way any other function call would be or represented as a block of
                code.

                2) Macros taken in isolation would not allow any strange changes to
                the language to be made (eg changing all *'s to +'s, or changing the
                behavior of existing classes - metaclasses, builtins and magic methods
                are required for this)

                3) Understanding a macro's behavior is typically easy for someone
                familiar with Python's syntax and constructs. In otherwords a Macro
                allows you to encapsulate commonly used idioms into a cleaner syntax,
                but would not allow you to alter the behavior of the language itself.

                My examples are barely touching the surface of what is possible with
                macros, but I wanted to start with some simple examples in order to
                give everyone some solid examples of what Macros are, and what Macros
                are not.

                Comment

                • Terry Reedy

                  #9
                  Re: macro FAQ


                  "Jacek Generowicz" <jacek.generowi cz@cern.ch> wrote in message
                  news:tyfbruf998 w.fsf@lxplus014 .cern.ch...[color=blue]
                  > This has turned out rather long, but I hope that it demystifies[/color]
                  these[color=blue]
                  > scary exotic macros for at least one or two people on the list.[/color]

                  Definitely. The sort of concrete example I asked for. Thank you.

                  Terry


                  Comment

                  • Michele Simionato

                    #10
                    Re: macro FAQ

                    Jacek Generowicz <jacek.generowi cz@cern.ch> wrote in message news:<tyfbruf99 8w.fsf@lxplus01 4.cern.ch>...[color=blue]
                    > ==== Example 1: a debugging aid =============== =============== ==
                    >
                    > One litte macro I have for debugging purposes (let's call it "show"),
                    > allows me to print out the source code of a number of expressions,
                    > along with their values. At this point, note that Python's horribly
                    > irregular syntax <0.5 wink> already starts causing problems: should
                    > the macro look like a block of code, or should it look like a function
                    > call; in Lisp both look identical.
                    >
                    > The "block" version of the show macro invocation:
                    >
                    > show:
                    > sin(x)
                    > a
                    > a + b + c
                    >
                    > The "function" version of the show macro invocation:
                    >
                    > show(sin(x), a, a + b + c)
                    >
                    > In both cases, the action of the macro should be to replace itself
                    > with its expansion, _before_ the compiler gets to see the source code.
                    > The expansion should look like this:
                    >
                    > print "sin(x) =>", sin(x)
                    > print "a =>", a
                    > print "a + b + c =>", a + b + c
                    >
                    > Note the key points:
                    >
                    > 1) The macro receives some data, and transforms it into valid Python
                    > source code
                    >
                    > 2) This happens before compile time
                    >
                    > 3) Nothing "outside" the macro call gets affected by the macro's
                    > action.
                    >
                    > Can this be implemented using metaclasses, or any other existing
                    > Python mechanism ?[/color]

                    Yes.



                    At the end it uses metaclasses+exe c+a simple argument parser based on
                    tokenize. EXPERIMENTAL code, which I would not trust except as proof
                    of concept.
                    [color=blue]
                    > === Example 2: Alexander Schmolck's updating classes ===============[/color]

                    I think this also can be done with metaclasses (somebody already
                    posted a recipe in some other thread, Diederich?)

                    Michele Simionato, Ph. D.
                    MicheleSimionat o@libero.it

                    --- Currently looking for a job ---

                    Comment

                    • Jacek Generowicz

                      #11
                      Re: macro FAQ

                      dtolton@yahoo.c om (Doug Tolton) writes:
                      [color=blue]
                      > Also note that the examples presented are purposefully trivial and
                      > could in many instances be accomplished other ways,[/color]

                      I hoped that the examples that I presented satisfied the requirements
                      that

                      a) They be simple enough to understand

                      b) not be (at least easily) implementable using existing Python
                      features

                      c) Not be completely useless

                      Did I fail ? :-)
                      [color=blue]
                      > Essentially Macros allow you to pass in some variables that are then
                      > expanded into valid Python syntax which is then executed.[/color]

                      Well, not just variables, data in general, some of which might be
                      variables, some of which might be variable names (identifiers) and
                      some of which might be (peudo-) code.
                      [color=blue]
                      > Question: Can't I accomplish this same functionality via string
                      > parsing and eval?
                      >
                      > Answer: Eval will accept any valid Python expression and execute it.
                      > This is however regarded by many as a security hole. Macros allow
                      > this type of expressiveness while limiting many of the security risks.
                      > With a Macro you can more specifically control what types of actions
                      > are permissible.[/color]

                      I don't think that this is relevant (or true, for that matter). Lisp
                      macros do not expand arbitrary data that a user passes in, they appear
                      as literals in your source code. The security issues are the same as
                      those surrounding "os.system( 'rm -rf /')" appearing literally in your
                      source code.

                      What is relevant, is the pain involved in doing it via strings. The
                      (pseudo) code that you pass to a Lisp macro, not only looks exactly
                      like Lisp code, but it is automatically tokenized and parsed for you,
                      and very easily manipulatable.
                      [color=blue]
                      > # Note, Jacek's method of using indentation is an interesting
                      > alternative to calling them as a
                      > # function.[/color]

                      It's probably worth pointing out, again, how important Lisp's
                      uniformity of syntax is, for its macro system. Generally speaking, a
                      macro accepts as arguments some mixture of data, identifiers and
                      expressions (let's forget about the existence of Python statements for
                      now, they complicate the situation even more). How do you pass in a
                      mixture of data and code?

                      Data is usually presented in a tuple:

                      foo(datum1, datum2, datum3)

                      Expressions are usually presented on separate lines:

                      def foo(...):
                      expression1
                      expression2
                      expression3

                      Let's try to think of what a Python with-open-file macro call would
                      look like.

                      In CL, with-open-file takes

                      1) a list containing an identifier (a symbol), a pathname (let's call
                      it a string) with some optional keywords.

                      2) arbitrary code

                      It then binds the identifer to a stream associated with the file, and
                      expands the source code inside an exception handling environment.

                      So, the expansion of a (simplistic) Python with_open_file might look
                      like this:

                      outfile = file("foo/bar", "w")
                      try:
                      print >> outfile, foo(...)
                      for i in range(10):
                      print >> outfile, bar(...)
                      except:
                      perform the necessary closing and cleaning up

                      But what should the corresponding call to with_open_file look like?

                      We have to pass in the identifier "outfile" (this is where it is very
                      handy to have symbols as a first-class data type, as in Lisp), and the
                      file name "foo/bar" ... but then we also have to pass in the chunk of
                      code

                      print >> outfile, foo(...)
                      for i in range(10):
                      print >> outfile, bar(i)

                      In Lisp it would look something like this:

                      (with-open-file (outfile "foo/bar" :direction :output)
                      (format outfile "~a" (foo ...))
                      (dotimes (i 10)
                      (format outfile "~&~a" (bar i))))

                      Now, I refuse to contemplate passing the source code in a string, in
                      the Python version.

                      Maybe we have to accept the distinction between data-like data, and
                      code-like data, having the macro accept both a tuple of arguments, and
                      blocks of code, so the call might look thus:

                      with_open_file( "outfile", "foo/bar", "w"):
                      code:
                      print >> outfile, foo(...)
                      for i in range(10):
                      print >> outfile, bar(...)

                      (If you need to pass in more than one code block, each one would go in
                      a seperate "code:" block.)

                      What could the definition look like?

                      defmacro with_open_file( stream, filename, mode)(block1)
                      expand(stream) = file(filename, mode)
                      try:
                      expand(block1)
                      except:
                      perform the necessary closing and clearing up

                      (expand would be a function which gets replaced by its argument, at
                      macro expansion time.)

                      Hmm, just about bearable, I guess, but I doubt that it generalizes
                      very well.

                      Note that we didn't transform the source code argument, just pasted it
                      in directly. If we wanted to manipulate it first, we'd be in for
                      serious suffering.
                      [color=blue]
                      > You could clearly accomplish this functionality using other means,[/color]

                      I think it is best to steer clear of such examples, as experience
                      shows that some people will not be able to resist the temptation to
                      conclude (and suggest) that there is no point to macros, and the
                      discussion gets derailed. We've seen enough of "you could do this
                      quite easily without macros, but ...", and not enough of "This would
                      be soooo painful without macros ..." (I won't say "impossible ", as
                      there is always Turing completeness.)

                      What was wrong with my original examples? I'd like to know, so that I
                      can replace them with better ones.

                      Comment

                      • Jacek Generowicz

                        #12
                        Re: macro FAQ

                        mis6@pitt.edu (Michele Simionato) writes:
                        [color=blue][color=green]
                        > > Can this be implemented using metaclasses, or any other existing
                        > > Python mechanism ?[/color]
                        >
                        > Yes.
                        >
                        > http://groups.google.it/groups?hl=it....lang.python.*[/color]

                        Unfortunately I can't easily access this at the moment. I'll try to
                        have a look later.
                        [color=blue]
                        > At the end it uses metaclasses+exe c+a simple argument parser based on
                        > tokenize. EXPERIMENTAL code, which I would not trust except as proof
                        > of concept.[/color]

                        If it uses exec, then it is faking up macros.

                        Lisp macros are little else besides offering language support for the
                        use of exec for this kind of thing.

                        If people start resorting to this sort of trick themselves, and
                        re-inventing it over and over again, then you might as well design it
                        properly, once and for all, and call it a macro system.

                        I submit that Python already has macros ... they just need a bit of
                        streamlining :-)

                        Comment

                        • Jacek Generowicz

                          #13
                          Re: macro FAQ

                          tebeka@cs.bgu.a c.il (Miki Tebeka) writes:
                          [color=blue]
                          > My personal favorites are the anaphoric macros (aif ...)[/color]

                          Though, you do realize that these are buggy, in terms of their
                          interaction with the package system :-)

                          Comment

                          • John J. Lee

                            #14
                            Re: macro FAQ

                            Jacek Generowicz <jacek.generowi cz@cern.ch> writes:
                            [color=blue]
                            > "Andrew Dalke" <adalke@mindspr ing.com> writes:
                            >[color=green]
                            > > Here's a proposed Q&A for the FAQ based on a couple recent threads.
                            > > Appropriate comments appreciated[/color]
                            >
                            > Such an FAQ item is probably a good idea.
                            >
                            > However, I think that we should distil out much of the opinion
                            > (particularly the opinions about opinions of others :-) and try to
                            > base it on fact:[/color]

                            I disagree. People reading a FAQ do want to know the opinion of
                            language users, and more importantly, of Guido, because that's what
                            explains why the language is as it is, and determines what will happen
                            in the future. That's fact too, just fact about people's opinions.

                            [color=blue]
                            > - what are macros (C-like and Lisp-like),
                            >
                            > - what are the technical difficulties with introducing them into
                            > Python[/color]

                            Arguably, these are both secondary issues given the fact that both
                            Guido (I presume?) and most Python users don't want macros. Obviously
                            some background should be in there explaining what macros are and how
                            they might apply to Python, but Andrew did just that.


                            [...snip useful technical criticism of Andrew's FAQ...][color=blue]
                            > Could you please give me a reference to someone "with plenty of
                            > experience using macros in Lisp" arguing this ?[/color]

                            Maybe he was referring to Laura Creighton? He posted a quote and a
                            link to another of her posts.


                            [...snip more technical points...][color=blue]
                            > But then, functions which provide an abstraction are also more
                            > difficult to write and understand than ones which merely "move code
                            > out of the way", and you'd have to think twice whether the abstraction
                            > is really useful, before deciding to pay the price for writing it, and
                            > making readers understand it.[/color]

                            I'm amazed that you say this. I think most programmers would disagree
                            with you here (certainly I do). Sure, abstract functions require some
                            work to understand the concept involved, but the important way in
                            which one function is easier or harder to understand than another has
                            to do with how much detail you need to know, not how hard the concepts
                            are. Needing to know details causes bugs. So does needing to know
                            concepts (though less often), but you can't get rid of the concepts,
                            whereas you *can* hide the details. And that's what abstraction is:
                            hiding details.

                            (and there's no need to answer here that you think macros are a good
                            way of hiding detail: we've gathered that ;-)

                            [...][color=blue]
                            > People in the music software "group" will find it hard to use code
                            > from people writing software for bioinformatics ... with or without
                            > macros. This has nothing to do with macros.[/color]

                            But people writing code using one bioinformatics library will not find
                            it hard to read code using another. That might not be the case if
                            macros were built-in.

                            [color=blue]
                            > OK, I promised some examples of macros. Note that I have not shown a
                            > single line of Lisp code in these threads, because I agree that it is
                            > likely to be meaningless to most readers of this group. I'll try
                            > continue without having to resort to Lisp examples.
                            >
                            > ==== Example 1: a debugging aid =============== =============== ==
                            >
                            > One litte macro I have for debugging purposes (let's call it "show"),
                            > allows me to print out the source code of a number of expressions,
                            > along with their values. At this point, note that Python's horribly[/color]
                            [...][color=blue]
                            > The "function" version of the show macro invocation:
                            >
                            > show(sin(x), a, a + b + c)[/color]
                            [...is equivalent to...][color=blue]
                            > print "sin(x) =>", sin(x)
                            > print "a =>", a
                            > print "a + b + c =>", a + b + c[/color]
                            [...][color=blue]
                            > Can this be implemented using metaclasses, or any other existing
                            > Python mechanism ?[/color]

                            Yes, using Lisp ;-P -- you can do this in Python with an emacs macro.

                            [color=blue]
                            > === Example 2: Alexander Schmolck's updating classes ===============
                            >
                            > Alexander recently expressed the desire to have all existing instances
                            > of a class be updated, when he changes the source of his class, and
                            > re-evaluates the definition.[/color]
                            [...]

                            There was a thread recently about how the problem behind this might be
                            solved in Python. I started it (a search for "DOM" or "4DOM" or
                            "hierarchy" and my email address should turn it up).

                            No, wait a minute -- instances, not classes?? Sounds like an abuse of
                            the language to me. What *is* the underlying problem to be solved
                            here?


                            John

                            Comment

                            • John J. Lee

                              #15
                              Re: macro FAQ

                              Jacek Generowicz <jacek.generowi cz@cern.ch> writes:
                              [color=blue]
                              > dtolton@yahoo.c om (Doug Tolton) writes:[/color]
                              [...][color=blue]
                              > I hoped that the examples that I presented satisfied the requirements
                              > that
                              >
                              > a) They be simple enough to understand
                              >
                              > b) not be (at least easily) implementable using existing Python
                              > features
                              >
                              > c) Not be completely useless
                              >
                              > Did I fail ? :-)[/color]

                              Yes. :-)


                              John

                              Comment

                              Working...