Forum: Ruby Sample for Metaprogramming

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
unknown (Guest)
on 2008-10-11 20:40
(Received via mailing list)
Hi.

Can anyone give me a good small sample for Metapgramming with Ruby? I
am new in Ruby and searching now samples to get a look into Ruby (I
also use IronRuby - when there will be a small sample which is also
working with IronRuby this would be wonderful).

Thanks!

Fridrich
Sebastian H. (Guest)
on 2008-10-11 21:38
(Received via mailing list)
removed_email_address@domain.invalid wrote:
> Can anyone give me a good small sample for Metapgramming with Ruby?

There you go:

require 'fileutils'
module Files
  extend self
  def in(dir)
    dir = File.expand_path(dir)

    Class.new do
      extend Enumerable
      @@dir = dir

      class <<self; self; end.class_eval do
        alias old_new new
        private :old_new

        def new(filename, contents=nil, &blk)
          if contents
            open("#{dirname}/#{filename}", "w") do |f|
              f.write contents
            end
          elsif blk
            open("#{dirname}/#{filename}", "w", &blk)
          else
            open("#{dirname}/#{filename}", "w") {}
          end
          old_new(filename)
        end

        def dirname() @@dir end

        def each()
          Dir.glob("#{dirname}/*") {|f| yield old_new(f)}
        end

        def to_s()
          "#{dirname}"
        end

        def inspect
          "Directory: #{self}"
        end

        Dir.glob("#{dir}/*") do |file|
          define_method(File.basename file) do
            old_new(File.basename file)
          end
        end
      end

      def initialize(filename)
        @filename = filename
      end

      def path()
        "#{self.class.dirname}/#{@filename}"
      end
      alias to_s path

      def inspect
        "File: #{self}"
      end

      def open(*args, &blk)
        Kernel.open(path, *args, &blk)
      end

      def delete
        FileUtils.rm(path)
        name = @filename
        class <<self.class; self end.class_eval do
          undef_method(name)
        end
      end
    end
  end
end

Ok, this took way more time to write than I expected and also turned out
quite
a bit bigger and isn't really tested very thoroughly. But the idea is a
such:

Using Files.in(dirname) you can get a class representing that directory.
This class will have a method for every file in that directory.
Calling such a method will give you an instance of the class,
representing the
specific file.
Calling new(filename) on the class will create a file in that directory.
The class is extended with Enumerable and you can use it to iterate over
its
instances representing the files that exist the directory.

Of course this is quite a complicated way to work with files, but you
wanted
meta-programming, so there you go.
(I did intend this to be simpler than it turned out to be, though)

HTH,
Sebastian
Ara H. (Guest)
on 2008-10-11 22:15
(Received via mailing list)
On Oct 11, 2008, at 10:37 AM, removed_email_address@domain.invalid wrote:

>
http://rubyquiz.com/quiz67.html

http://kinderman.net/articles/2007/09/22/learning-...


a @ http://codeforpeople.com/
James G. (Guest)
on 2008-10-13 00:39
(Received via mailing list)
On Oct 11, 2008, at 11:37 AM, removed_email_address@domain.invalid wrote:

> Can anyone give me a good small sample for Metapgramming with Ruby?

The Pragmatic Programmers have a series of screencasts about this:

http://www.pragprog.com/screencasts/v-dtrubyom/the...

James Edward G. II
Chad P. (Guest)
on 2008-10-14 22:39
(Received via mailing list)
On Sun, Oct 12, 2008 at 02:35:34AM +0900, Sebastian H. wrote:
> removed_email_address@domain.invalid wrote:
> > Can anyone give me a good small sample for Metapgramming with Ruby?
>
> There you go:

[snip]

> instances representing the files that exist the directory.
>
> Of course this is quite a complicated way to work with files, but you wanted
> meta-programming, so there you go.
> (I did intend this to be simpler than it turned out to be, though)

Is there anyone here that knows Lisp well enough to provide a Lisp
example that does the same thing, just for purposes of comparing how the
two languages handle these techniques?
Sebastian H. (Guest)
on 2008-10-15 19:31
(Received via mailing list)
Chad P. wrote:
> Is there anyone here that knows Lisp well enough to provide a Lisp
> example that does the same thing, just for purposes of comparing how the
> two languages handle these techniques?

That's pretty complicated. The first step would be to define what "the
same
thing" is in lisp. Lisp doesn't really have the concept of calling
methods on
an object, so you'd have to come up with something else. And at that
point it
would be kinda hard to compare the implementations, because they'd
implement
somewhat different things.
Chad P. (Guest)
on 2008-10-15 22:24
(Received via mailing list)
On Thu, Oct 16, 2008 at 12:27:05AM +0900, Sebastian H. wrote:
> Chad P. wrote:
> > Is there anyone here that knows Lisp well enough to provide a Lisp
> > example that does the same thing, just for purposes of comparing how the
> > two languages handle these techniques?
>
> That's pretty complicated. The first step would be to define what "the same
> thing" is in lisp. Lisp doesn't really have the concept of calling methods on
> an object, so you'd have to come up with something else. And at that point it
> would be kinda hard to compare the implementations, because they'd implement
> somewhat different things.

I'm aware of the existence of CLOS, but don't really know anything about
its specifics of implementation and use.  How does it handle the kind of
functionality that, in Ruby, consists of sending messages to objects to
invoke their methods?

Should we take this off-list?
Sebastian H. (Guest)
on 2008-10-15 23:53
(Received via mailing list)
Chad P. wrote:
> I'm aware of the existence of CLOS, but don't really know anything about
> its specifics of implementation and use.  How does it handle the kind of
> functionality that, in Ruby, consists of sending messages to objects to
> invoke their methods?

It doesn't, really. CLOS methods are overloadable functions basically,
i.e.
you can define multiple methods of the same name, but with different
argument
types, and it'll pick the right one to call depending on the type(s) of
the
object(s) you pass as arguments. There's no concept of a receiver
though.

> Should we take this off-list?

Well, since we're discussing CLOS in the context of comparing it to
ruby, it's
still kinda on-topic, so unless someone complains, I see no reason not
to
continue this discussion here on the list.

HTH,
Sebastian
Eric S. (Guest)
on 2008-10-16 02:16
(Received via mailing list)
Chad P. <removed_email_address@domain.invalid> writes:

> Should we take this off-list?

I'm enjoying following this discussion on list, if you do take it off,
please include me.  Thanks -- Eric
Chad P. (Guest)
on 2008-10-16 03:52
(Received via mailing list)
On Thu, Oct 16, 2008 at 04:53:04AM +0900, Sebastian H. wrote:
> Chad P. wrote:
> > I'm aware of the existence of CLOS, but don't really know anything about
> > its specifics of implementation and use.  How does it handle the kind of
> > functionality that, in Ruby, consists of sending messages to objects to
> > invoke their methods?
>
> It doesn't, really. CLOS methods are overloadable functions basically, i.e.
> you can define multiple methods of the same name, but with different argument
> types, and it'll pick the right one to call depending on the type(s) of the
> object(s) you pass as arguments. There's no concept of a receiver though.

So, basically, instead of real methods, CLOS just uses . . . what?
Parametric polymorphism?  This isn't meant as a challenge or complaint,
but rather just a question so I'll understand it better:

What about CLOS makes it "object oriented"?


>
> > Should we take this off-list?
>
> Well, since we're discussing CLOS in the context of comparing it to ruby, it's
> still kinda on-topic, so unless someone complains, I see no reason not to
> continue this discussion here on the list.

Works for me.
Chad P. (Guest)
on 2008-10-16 03:55
(Received via mailing list)
On Thu, Oct 16, 2008 at 07:16:10AM +0900, Eric S. wrote:
> Chad P. <removed_email_address@domain.invalid> writes:
>
> > Should we take this off-list?
>
> I'm enjoying following this discussion on list, if you do take it off,
> please include me.  Thanks -- Eric

Noted.
Joel VanderWerf (Guest)
on 2008-10-16 05:52
(Received via mailing list)
Chad P. wrote:
>
> So, basically, instead of real methods, CLOS just uses . . . what?
> Parametric polymorphism?  This isn't meant as a challenge or complaint,
> but rather just a question so I'll understand it better:

IIRC: CLOS uses generic functions, aka multimethod dispatch. Think of a
hash table that maps n-tuples of classes to implementation functions.
Eric S. (Guest)
on 2008-10-16 05:58
(Received via mailing list)
Chad P. <removed_email_address@domain.invalid> writes:

>> object(s) you pass as arguments. There's no concept of a receiver though.
>
> So, basically, instead of real methods, CLOS just uses . . . what?
> Parametric polymorphism?  This isn't meant as a challenge or complaint,
> but rather just a question so I'll understand it better:
>

The following begins with a good overview of the rational behind the use
of generic functions in CLOS instead of using a message passing system
as used in ruby.

http://www.dreamsongs.com/Files/ECOOP.pdf

linked to from

http://www.dreamsongs.com/CLOS.html

It makes the good point that generic functions are a natural solution in
any lisp.  The paper states...

|      Furthermore, in Common Lisp, arithmetic operators are already
| generic in a certain sense. The expression
|
|      (+ x y)
|
| does not imply that x and y are of any particular type, nor does it
| imply that they are of the same type. For example, x might be an
| integer and y a complex number, and the + operation is required to
| perform the correct coercions and produce an appropriate result.
|
|      Because the Object System is a system for Common Lisp, it is
| important that generic functions be first-class objects and that the
| concept of generic functions be an extension and a generalization of
| the concept of Common Lisp functions. In this way, the Object System
| is a natural and smooth extension of Common Lisp.

Also, CLOS contains mechanisms for implementing a message-passing based
object system.  Again from the paper...

|  Despite the advantages of generic functions, there may at times be
|  reasons for preferring a message-passing style; such a style can be
|  implemented by means of generic functions or by means of the Common
|  Lisp Object System Meta-Object Protocol.

I would very much like to see any implementation of a ruby-like message
based object system using CLOS.

>
> What about CLOS makes it "object oriented"?
>

The fact that it provides for the creation of objects which are
instances of classes, and provides for inheritance between classes. :)

-- Eric
This topic is locked and can not be replied to.