Macros in Ruby

Discussion in 'Ruby' started by George Moschovitis, Aug 2, 2004.

  1. Hello everyone,

    one of the features of the LISP family of languages that is missing from
    Ruby are macros. I think they are useful on a lot of occasions so
    I would like to see Ruby support macros in the future.

    However i think it is quite easy to emulate some form of macro
    functionality in Ruby. Here is some simple code:

    macros.rb:
    ----------

    $__macros__ = {}
    $__required__ = {}

    module Kernel

    alias_method :eek:ld_require, :require
    def require(path)
    return if $__required__[path]

    source = open(path) { |f|
    f.sysread(f.stat().size())
    }

    # parse macro
    source.gsub!(/defmacro\s*\/(.*?)\/\s(.*?)endmacro/m) {
    $__macros__[Regexp.new($1)] = $2 ; ""
    }

    # expand macros
    $__macros__.each { |match, replace|
    source.gsub!(match, replace)
    }

    $__required__[path] = true

    eval(source)
    end

    end

    require "test1.rb"
    require "test2.rb"


    test1.rb:
    ---------

    defmacro /my_macro\((.*)\)/
    begin
    my_function(\1)
    rescue => ex
    puts ex
    end
    endmacro

    # php style foreach
    defmacro /foreach\s*\((.*)\s*as(.*)\)/
    for \2 in \1
    endmacro

    def my_function(str)
    puts str
    end

    class TestClass
    def another_test
    words = %w{ simple test }
    foreach(words as word)
    puts k
    end
    end
    end


    test2.rb:
    ---------

    value = "Hello World!"
    my_macro(value)

    numbers = [1, 2, 3, 4]

    foreach (numbers as i)
    puts i
    end

    a = TestClass.new
    a.another_test()



    Once again i was suprised to find out that Ruby is so powerful!

    However I would like to hear your opinion on this code. Is there any
    problem I have overlooked? Is there a better implementation? Could this
    be better designed?

    If anyone finds it usefull I could create a small package with
    doc+examples and upload it to RAA.


    have fun,
    George Moschovitis

    --
    www.navel.gr
    www.joy.gr
    George Moschovitis, Aug 2, 2004
    #1
    1. Advertising

  2. George Moschovitis

    Guest

    * George Moschovitis <> [2004-08-02 18:16:35 +0900]:

    > Hello everyone,
    >
    > one of the features of the LISP family of languages that is missing from
    > Ruby are macros. I think they are useful on a lot of occasions so
    > I would like to see Ruby support macros in the future.
    >
    > However i think it is quite easy to emulate some form of macro
    > functionality in Ruby. Here is some simple code:


    I've heard Matz say that Ruby will not support macros.
    They are too easily abused and can mutate the language.
    Besides, you can achieve the same powerful affect using
    blocks.

    Jim
    , Aug 2, 2004
    #2
    1. Advertising

  3. George Moschovitis wrote:
    > Hello everyone,
    >
    > one of the features of the LISP family of languages that is missing from
    > Ruby are macros. I think they are useful on a lot of occasions so
    > I would like to see Ruby support macros in the future.


    What you have defined are more like C macros, rather than LISP macros,
    which are hygienic (they operate at the level of syntactic elements,
    rather than characters).
    Joel VanderWerf, Aug 2, 2004
    #3
  4. > I've heard Matz say that Ruby will not support macros.
    > They are too easily abused and can mutate the language.


    I 've heard that, but macros ARE usefull. Take a look
    at www.paulgraham.com for example.

    > Besides, you can achieve the same powerful affect using
    > blocks.


    How can i use blocks to emulate macros ? I cannot understand
    that.

    George

    --
    www.navel.gr
    www.joy.gr
    George Moschovitis, Aug 2, 2004
    #4
  5. Joel VanderWerf wrote:
    > What you have defined are more like C macros, rather than LISP macros,
    > which are hygienic (they operate at the level of syntactic elements,
    > rather than characters).


    You are of course right. But you can do still usefull things. And I
    think it can be improved. Any ideas are welcome. Even better would be
    support for macros in Ruby 1.9 :)

    George.


    --
    www.navel.gr
    www.joy.gr
    George Moschovitis, Aug 2, 2004
    #5
  6. George Moschovitis

    James Britt Guest

    Joel VanderWerf wrote:
    > George Moschovitis wrote:
    >
    >> Hello everyone,
    >>
    >> one of the features of the LISP family of languages that is missing from
    >> Ruby are macros. I think they are useful on a lot of occasions so
    >> I would like to see Ruby support macros in the future.

    >
    >
    > What you have defined are more like C macros, rather than LISP macros,
    > which are hygienic (they operate at the level of syntactic elements,
    > rather than characters).


    Would Ruby macros, in the Lisp sense, have to manipulate the AST?

    And a question (ideally) for Matz, but comments from anyone else are of
    course welcome:

    Would true macros in Ruby be more prone to abuse than they are in Lisp?

    Is there something different about Ruby such that what (supposedly)
    works to such acclaim in Lisp would be inappropriate in Ruby?


    Thanks,



    James
    James Britt, Aug 2, 2004
    #6
  7. On Tue, 3 Aug 2004 02:29:34 +0900, James Britt
    <> wrote:
    > Is there something different about Ruby such that what (supposedly)
    > works to such acclaim in Lisp would be inappropriate in Ruby?


    A: S-expressions, or the lack thereof in Ruby. Lisp code can always be
    manipulated as a simple tree of cons cells; Ruby code, even if a
    high-level programmatic interface existed to the AST, has a much
    richer syntax, and therefore more complex structure.

    Also, as has been mentioned, Ruby largely replaces macros with blocks
    -- they allow delayed evaluation, specialized iteration and
    pre/post-condition checks, etc. Many of the common macros you'll see
    in Lisp are things like this:

    (with-open-file "foo.dat" my-file (case (read-char my-file) ...))

    [my apologies for the weird function names; it's been a couple of
    years since I was actively developing any Lisp code]

    Obviously, that example is quite handily supported by the more
    Ruby-esque example below:

    open("foo.dat") {|my_file| case my_file.getc ...}

    Personally, I think macros could be an interesting tool for very
    special cases, but they're not an essential feature for 90% of
    developers. Now, exposing the AST with a high-level API could have
    other benefits: code analysis and optimization, JIT compilers,
    documentation generators, etc.

    Lennon
    Lennon Day-Reynolds, Aug 2, 2004
    #7
  8. George Moschovitis

    Phil Tomson Guest

    In article <cel0la$2sto$>,
    George Moschovitis <> wrote:
    >Hello everyone,
    >
    >one of the features of the LISP family of languages that is missing from
    >Ruby are macros. I think they are useful on a lot of occasions so
    >I would like to see Ruby support macros in the future.
    >

    <code snipped>


    >Once again i was suprised to find out that Ruby is so powerful!
    >
    >However I would like to hear your opinion on this code. Is there any
    >problem I have overlooked? Is there a better implementation? Could this
    >be better designed?
    >
    >If anyone finds it usefull I could create a small package with
    >doc+examples and upload it to RAA.
    >
    >
    >have fun,
    >George Moschovitis


    I've never used Lisp so I'm not too familiar with Lisp macros and I know
    that Matz isn't too fond of macros. However, I can't help feeling that
    you've created something quite cool here and I'd certainly like to see
    more.



    Please do post something on the RAA! Maybe you could put it up on
    rubyforge?

    Phil
    Phil Tomson, Aug 2, 2004
    #8
  9. George Moschovitis

    Phil Tomson Guest

    In article <>, <> wrote:
    >* George Moschovitis <> [2004-08-02 18:16:35 +0900]:
    >
    >> Hello everyone,
    >>
    >> one of the features of the LISP family of languages that is missing from
    >> Ruby are macros. I think they are useful on a lot of occasions so
    >> I would like to see Ruby support macros in the future.
    >>
    >> However i think it is quite easy to emulate some form of macro
    >> functionality in Ruby. Here is some simple code:

    >
    >I've heard Matz say that Ruby will not support macros.


    True, Matz has said that. But if we can do something Macro-like with a
    module (as George has shown) then it's optional.

    >They are too easily abused and can mutate the language.
    >Besides, you can achieve the same powerful affect using
    >blocks.
    >


    Not quite. Notice that George introduced totally new 'syntax' using his
    'macros' - you can't do that with blocks.


    Phil
    Phil Tomson, Aug 2, 2004
    #9
  10. George Moschovitis

    Phil Tomson Guest

    In article <>,
    Lennon Day-Reynolds <> wrote:
    >
    >Personally, I think macros could be an interesting tool for very
    >special cases, but they're not an essential feature for 90% of
    >developers. Now, exposing the AST with a high-level API could have
    >other benefits: code analysis and optimization, JIT compilers,
    >documentation generators, etc.
    >


    ....and code translators, and lots of other cool things.

    Yes, this would be great to have.

    Phil
    Phil Tomson, Aug 2, 2004
    #10
  11. On Tue, Aug 03, 2004 at 12:45:02AM +0900, wrote:
    > I've heard Matz say that Ruby will not support macros.
    > They are too easily abused and can mutate the language.
    > Besides, you can achieve the same powerful affect using
    > blocks.


    I've sometimes found myself wanting macros for things that *cannot* be
    done with blocks currently; however, in most cases they could have been
    accomplished easily had the often proposed extensions to Binding and
    Kernel#caller been implemented.

    --
    Running Debian GNU/Linux Sid (unstable)
    batsman dot geo at yahoo dot com
    Mauricio Fernández, Aug 2, 2004
    #11
  12. George Moschovitis

    Phil Tomson Guest

    In article <cel0la$2sto$>,
    George Moschovitis <> wrote:
    >Hello everyone,
    >
    >one of the features of the LISP family of languages that is missing from
    >Ruby are macros. I think they are useful on a lot of occasions so
    >I would like to see Ruby support macros in the future.
    >
    >However i think it is quite easy to emulate some form of macro
    >functionality in Ruby. Here is some simple code:
    >
    >macros.rb:
    >----------
    >
    >$__macros__ = {}
    >$__required__ = {}
    >
    >module Kernel
    >
    >alias_method :eek:ld_require, :require
    >def require(path)
    > return if $__required__[path]
    >
    > source = open(path) { |f|
    > f.sysread(f.stat().size())
    > }
    >
    > # parse macro
    > source.gsub!(/defmacro\s*\/(.*?)\/\s(.*?)endmacro/m) {
    > $__macros__[Regexp.new($1)] = $2 ; ""
    > }
    >
    > # expand macros
    > $__macros__.each { |match, replace|
    > source.gsub!(match, replace)
    > }
    >
    > $__required__[path] = true
    >
    > eval(source)
    >end
    >
    >end
    >
    >require "test1.rb"
    >require "test2.rb"
    >
    >
    >test1.rb:
    >---------
    >
    >defmacro /my_macro\((.*)\)/
    > begin
    > my_function(\1)
    > rescue => ex
    > puts ex
    > end
    >endmacro
    >
    ># php style foreach
    >defmacro /foreach\s*\((.*)\s*as(.*)\)/
    > for \2 in \1
    >endmacro
    >
    >def my_function(str)
    > puts str
    >end
    >
    >class TestClass
    > def another_test
    > words = %w{ simple test }
    > foreach(words as word)
    > puts k
    > end
    > end
    >end
    >
    >
    >test2.rb:
    >---------
    >
    >value = "Hello World!"
    >my_macro(value)
    >
    >numbers = [1, 2, 3, 4]
    >
    >foreach (numbers as i)
    > puts i
    >end
    >
    >a = TestClass.new
    >a.another_test()
    >
    >
    >
    >Once again i was suprised to find out that Ruby is so powerful!
    >
    >However I would like to hear your opinion on this code. Is there any
    >problem I have overlooked? Is there a better implementation? Could this
    >be better designed?


    Another comment: maybe instead of redefining 'require' you should just
    have another method on kernel, something like 'load_macro' or
    'require_macro'? This would make it clear that you are loading code which
    contains macros. Perhaps even the file extension should be different for
    these files to avoid confusion (*.rbm?).

    Also, right now you can only define these macros in files that get
    required, maybe you should also allow for the definition of macros in
    strings or here-docs?

    Phil
    Phil Tomson, Aug 2, 2004
    #12
  13. George Moschovitis

    Phil Tomson Guest

    In article <-stuttgart.de>,
    Mauricio Fernández <> wrote:
    >On Tue, Aug 03, 2004 at 12:45:02AM +0900, wrote:
    >> I've heard Matz say that Ruby will not support macros.
    >> They are too easily abused and can mutate the language.
    >> Besides, you can achieve the same powerful affect using
    >> blocks.

    >
    >I've sometimes found myself wanting macros for things that *cannot* be
    >done with blocks currently; however, in most cases they could have been
    >accomplished easily had the often proposed extensions to Binding and
    >Kernel#caller been implemented.
    >

    Can you give some examples?

    Phil
    Phil Tomson, Aug 2, 2004
    #13
  14. Hello jim,

    >> However i think it is quite easy to emulate some form of macro
    >> functionality in Ruby. Here is some simple code:


    jfo> I've heard Matz say that Ruby will not support macros.

    And i hope that he never changes his opinion at this topic.

    jfo> They are too easily abused and can mutate the language.

    They easily make code much more unreadable. I think that languages
    like D, C# etc now exactly why they don't want something like macros.

    As said before lisp is different because of the general S-Expression
    style of this language.

    I remember an asian saying about thinks like this:

    "Der Kluge fügt jeden Tag etwas hinzu,
    Der Weise entfernt jeden Tag etwas".

    Translated to english it is something like:

    "The clever man adds something every day,
    The wise man removes something every day".


    --
    Best regards, emailto: scholz at scriptolutions dot com
    Lothar Scholz http://www.ruby-ide.com
    CTO Scriptolutions Ruby, PHP, Python IDE 's
    Lothar Scholz, Aug 2, 2004
    #14
  15. Hi --

    On Tue, 3 Aug 2004, James Britt wrote:

    > Joel VanderWerf wrote:
    > > George Moschovitis wrote:
    > >
    > >> Hello everyone,
    > >>
    > >> one of the features of the LISP family of languages that is missing from
    > >> Ruby are macros. I think they are useful on a lot of occasions so
    > >> I would like to see Ruby support macros in the future.

    > >
    > >
    > > What you have defined are more like C macros, rather than LISP macros,
    > > which are hygienic (they operate at the level of syntactic elements,
    > > rather than characters).

    >
    > Would Ruby macros, in the Lisp sense, have to manipulate the AST?
    >
    > And a question (ideally) for Matz, but comments from anyone else are of
    > course welcome:
    >
    > Would true macros in Ruby be more prone to abuse than they are in Lisp?
    >
    > Is there something different about Ruby such that what (supposedly)
    > works to such acclaim in Lisp would be inappropriate in Ruby?


    I'm answering from not very much knowledge of Lisp, and I know the
    meta-meta-meta people disagree :) but in the form this idea has
    always been represented to me -- namely, as a way to introduce
    essentially arbitrary syntax -- I've found it unappealing. I think
    Ruby can be great for application language things, but the idea of
    having {} or . mean new things doesn't do much for me.

    I guess I prefer to think of Ruby as a language with a certain syntax
    than as a kind of host environment for syntax definition. That's
    partly because I like Ruby's syntax, and I think Matz is better at
    designing syntax than most of us would be :) And also because the
    thought of having to learn new syntax for, potentially, every program
    is daunting.


    David

    --
    David A. Black
    David A. Black, Aug 2, 2004
    #15
  16. Hello Jesse,

    JJ> Banning a feature because it can be misused is a pretty weak rationale.

    Banning an often misused features because it does not fit in the style of a
    language is a very good rationale.


    Read the chapter "On language design and evolution" from
    http://www2.inf.ethz.ch/~meyer/ongoing/etl/#table

    Username: "Talkitover"
    Password: "etl3"
    Yes this is a public accessable page !


    --
    Best regards, emailto: scholz at scriptolutions dot com
    Lothar Scholz http://www.ruby-ide.com
    CTO Scriptolutions Ruby, PHP, Python IDE 's
    Lothar Scholz, Aug 2, 2004
    #16
  17. On Tuesday, August 3, 2004, 8:01:38 AM, Jesse wrote:

    > In article <>, Lothar
    > Scholz <> wrote:


    >> Hello jim,
    >>
    >> >> However i think it is quite easy to emulate some form of macro
    >> >> functionality in Ruby. Here is some simple code:

    >>
    >> jfo> I've heard Matz say that Ruby will not support macros.
    >>
    >> And i hope that he never changes his opinion at this topic.
    >>
    >> jfo> They are too easily abused and can mutate the language.
    >>
    >> They easily make code much more unreadable.


    > Banning a feature because it can be misused is a pretty weak rationale.
    > It might make sense for something like goto where you can provide more
    > structured alternatives that take care of most cases, but I don't think
    > macros fall into this case.


    > It's been said in this thread that Ruby doesn't need macros because it
    > has blocks but, this too, seems like a very weak argument. After all
    > Lisp is famous for its support for closures and Lisp programmers still
    > value the maro support in Lisp.


    That itself is a weak argument. Elsewhere in the thread it was
    mentioned that most uses of macros in LISP are to do what Ruby does
    naturally with blocks. Your statement implies that Ruby blocks are
    equivalent to LISP closures, which is untrue.

    >>From what I can tell macros offer three benefits: 1) They allow you to

    > extend the syntax of the language to directly support your problem
    > domain. For example, if you work with finite-state machines you can
    > write a macro that allows you to declaratively define FSMs.


    I bet it's easy to declaritively define FSMs in Ruby. But beyond
    that, mere talk of "extending syntax" doesn't translate from LISP to
    Ruby, as LISP doesn't have anything recognisable as programming
    language syntax.

    > 2) Macros allow you to evaluate arguments zero or more times whereas
    > functions and blocks normally eagerly evaluate arguments once.


    Yes, nice idea. My very limited understanding is that this is
    typically used to implement control structures commonly found in other
    languages.

    > 3) Macros are inlined so they may execute faster than a block.


    That's just a speed issue, which Matz is addressing in other ways.

    > Of these benefits, blocks only address point two and that in a rather
    > clunky fashion.



    >> As said before lisp is different because of the general S-Expression
    >> style of this language.


    > Different only in that it's easier to implement macros in Lisp. But
    > more conventional languages, like Dylan, also support macros.


    So it's an implementation issue. But when the difficulty of
    implementation becomes large, the rationale for doing so must become
    strong. I know that IANAL (I am being anal), but you have to
    demonstrate some real benefit to Ruby, not benefit to LISP.

    Cheers,
    Gavin
    Gavin Sinclair, Aug 3, 2004
    #17
  18. George Moschovitis

    James Britt Guest

    Jesse Jones wrote:
    >
    > Banning a feature because it can be misused is a pretty weak rationale.


    I tend to agree on this, preferring an enabling language to a B&D
    language. Ruby already gives folks plenty of tools for making code
    unreadable. I think most people would use macros to do the opposite:
    encapsulate some abstraction to make code cleaner.

    David Alan Black mentioned macros as (possibly) a facility for
    introducing arbitrary syntax. I'm no Lisper, but no examples I've seen
    of Lisp macros suggest that this is what goes on. I do not think you
    can use Lisp macros to get a Lisp interpreter to under truly arbitrary code.

    But, even supposing one could, I believe the Darwinian forces in a
    development community would prevent abuse of macros from becoming prevalent.
    James Britt, Aug 3, 2004
    #18
  19. Hi --

    On Tue, 3 Aug 2004, James Britt wrote:

    > David Alan Black mentioned macros as (possibly) a facility for
    > introducing arbitrary syntax. I'm no Lisper, but no examples I've seen
    > of Lisp macros suggest that this is what goes on. I do not think you
    > can use Lisp macros to get a Lisp interpreter to under truly arbitrary code.


    My ignorance of Lisp macros is almost complete. Mainly I was going by
    the (possibly completely wrong) impression that what people usually
    mean by "having macros in Ruby" is allow on-the-fly redefinition of
    syntax, including punctuation.


    David

    --
    David A. Black
    David A. Black, Aug 3, 2004
    #19
  20. George Moschovitis

    Phil Tomson Guest

    In article <>,
    James Britt <> wrote:
    >Jesse Jones wrote:
    > >
    >> Banning a feature because it can be misused is a pretty weak rationale.

    >
    >I tend to agree on this, preferring an enabling language to a B&D
    >language. Ruby already gives folks plenty of tools for making code
    >unreadable. I think most people would use macros to do the opposite:
    >encapsulate some abstraction to make code cleaner.
    >
    >David Alan Black mentioned macros as (possibly) a facility for
    >introducing arbitrary syntax. I'm no Lisper, but no examples I've seen
    >of Lisp macros suggest that this is what goes on. I do not think you
    >can use Lisp macros to get a Lisp interpreter to under truly arbitrary code.
    >
    >But, even supposing one could, I believe the Darwinian forces in a
    >development community would prevent abuse of macros from becoming prevalent.
    >


    Agreed.

    While Matz may have 'banned' macros from the core language, that doesn't
    mean that if someone comes up with a way to do LISP-like macros
    implemented in an external module, (that could be downloaded
    from the RAA for example) that Matz would ban the module. He probably
    would never consider bundling it with the Ruby distribution, of course,
    but that doesn't mean it would be 'banned'.

    If such a module did ever become available those who would be interested
    in such things would use it and those who were not interested would
    ignore it.

    It's kind of like how the static typing advocates occasionally come up
    with some code for emulating static typing in Ruby (and you can probably
    find some on the RAA) while most of us think that such things are
    ill-advised, no one is stopping the advocates of such things from using
    it.

    Phil
    Phil Tomson, Aug 3, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    80
    Views:
    2,425
    Stephen J. Bevan
    Nov 7, 2003
  2. Replies:
    1
    Views:
    445
    Marco Antoniotti
    Oct 7, 2003
  3. Replies:
    5
    Views:
    495
  4. Michael T. Babcock

    Re: Explanation of macros; Haskell macros

    Michael T. Babcock, Nov 3, 2003, in forum: Python
    Replies:
    0
    Views:
    516
    Michael T. Babcock
    Nov 3, 2003
  5. Andrew Arro

    macros-loop? calling macros X times?

    Andrew Arro, Jul 23, 2004, in forum: C Programming
    Replies:
    2
    Views:
    493
    S.Tobias
    Jul 24, 2004
Loading...

Share This Page