Sample for Metaprogramming


#1

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


#2

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


#3

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-ruby-object-model-and-metaprogramming

James Edward G. II


#4

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-ruby-meta-programming-with-metakoans

a @ http://codeforpeople.com/


#5

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?


#6

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.


#7

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?


#8

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


#9

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.


#10

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.


#11

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.


#12

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


#13

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. :slight_smile:

– Eric