[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[ANN] (Real) Primitive Ruby Generics support

Isaac Devine

12/27/2005 9:59:00 AM

Hi all,

I have been hacking away to create a simple library that adds
generics-like qualities to ruby. At the moment you can define methods
with type-matches, defaults if no match and different number of
argument matches. Currently thinking about adding pattern-matching
support from eigenclass blog. Depends on ruby facets.

Usage examples (Tests) are at the bottom.
Any suggestions, comments, flames ;-) ?

thanks,
Isaac Devine
P.S. BSD licensed. (don't know about the bit from why's guide though...)

--------------generics.rb--------------
# This file contains all you need to add generics to any ruby class :)
# ie.
# class Sample
# include Generics
# generic_method :name, Types do
# CODE
# end
## Default case
# generic_method :name do
# CODE
# end
# end
require 'mega/inheritor'

# This Object stuff from Why's Metaprogramming guide
class Object
# The hidden singleton lurks behind everyone
def metaclass; class << self; self; end; end
def meta_eval &blk; metaclass.instance_eval &blk; end

# Adds methods to a metaclass
def meta_def name, &blk
meta_eval { define_method name, &blk }
end

# Defines an instance method within a class
def class_def name, &blk
class_eval { define_method name, &blk }
end
end
# End Why's Stuff.

module Generics
class_inherit do
# Get a metaclass for this class
def metaclass; class << self; self; end; end

# metaprogramming code for generic_method
def generic_method(method_name, *types, &blk )
# have a class instance hash which holds the following:
# { :method_name => { type_name => block, type_name => block } }
# initialize it here...
class_eval {
# define the class generic_signatures if they don't exist
@generic_signatures = Hash.new if not
defined?(@generic_signatures) # define the generic method's signatures
if they don't exist @generic_signatures[method_name] = Hash.new unless
@generic_signatures.has_key?(method_name)
def self.generic_signatures
return @generic_signatures
end
}

# check to see if we are the default
if types.empty?
class_eval {
@generic_signatures[method_name].default = blk
}
else # got a typelist?
# create the type "string"
specific_method_name = types.join("_").to_sym
class_eval {
@generic_signatures[method_name][specific_method_name] = blk
}
end

# define the class method that does the dispatch to
# the appropiate block.
class_def(method_name) do |*args|
type_sig_arr = args.collect { |a| a.class }
type_sig = type_sig_arr.join('_').to_sym
self.class.generic_signatures[method_name][type_sig].call(*args)
end
end

end
end

class Test
include Generics
generic_method :get, String do |arg|
puts "In String... -- #{arg}"
end

generic_method :get, Fixnum do |arg|
puts "In Fixnum... -- #{arg}"
end
end

class Test2
include Generics
generic_method :two_args, String, Fixnum do |arg1, arg2|
puts "got a String and Fixnum"
end
generic_method :two_args, String, String do |arg1, arg2|
puts "got two Strings"
end
end
# does having a method that accepts two different numbers
# of arguments work?
class TestVariable
include Generics
generic_method :test_method, String do |arg1|
puts "single argument"
end

generic_method :test_method, String, Fixnum do |arg1,arg2|
puts "two arguments"
end
end

class TestDefault
include Generics

generic_method :test, String do |arg|
puts "in String!"
end

generic_method :test do |arg|
puts "The rest!"
end
end


17 Answers

dblack

12/27/2005 10:46:00 AM

0

James Gray

12/27/2005 1:57:00 PM

0

On Dec 27, 2005, at 4:46 AM, dblack@wobblini.net wrote:

> On Tue, 27 Dec 2005, Isaac Devine wrote:
>
>> eigenclass blog
>
> Call singleton classes singleton classes, not metaclasses or
> eigenclasses :-)

Just to be clear, the original post wasn't inventing terminology, it
was referring to a blog:

http://eigen...

James Edward Gray II



gabriele renzi

12/27/2005 4:32:00 PM

0

Isaac Devine ha scritto:
> Hi all,
>
> I have been hacking away to create a simple library that adds
> generics-like qualities to ruby. At the moment you can define methods
> with type-matches, defaults if no match and different number of
> argument matches. Currently thinking about adding pattern-matching
> support from eigenclass blog. Depends on ruby facets.
>
> Usage examples (Tests) are at the bottom.
> Any suggestions, comments, flames ;-) ?
>
> thanks,
> Isaac Devine

I think you could be intererested in the StrongTyping module
http://raa.ruby-lang.org/project/str...

Florian Groß

12/28/2005 2:24:00 PM

0

Isaac Devine

12/29/2005 3:13:00 AM

0

On Wed, 28 Dec 2005 23:24:01 +0900
Florian Groß <florgro@gmail.com> wrote:
> > I have been hacking away to create a simple library that adds
> > generics-like qualities to ruby. At the moment you can define
> > methods with type-matches, defaults if no match and different
> > number of argument matches.
>
> Been there, done that:
>
> http://ruby-contract.ruby...
>
> New ideas are very welcome.
>

Thanks! I've quickly looked at the ruby-doc for that. It's seems to
only be able to specific "contracts" for classes, with method
signatures as a subset. What my goal for generics is to be able to
choose what code to execute based on method/class parameter types.
ie.
converting :
def foo(arg)
if arg.kind_of? String
puts "it is a string! reverse it! #{arg.reverse}"
elsif arg.kind_of? Fixnum
puts "Fixnum! double it! #{2*arg}"
end
end

into:

generic_method :foo, String do |arg|
puts "it is a string! reverse it! #{arg.reverse}"
end

generic_method :foo, Fixnum do |arg|
puts "Fixnum! double it! #{2*arg}"
end

In the future I would like to be able to extend this to classes as
well. One implication of this we will be the ability to get rid of
"adapter" classes when joining heirachys. One example would be adding
support to reading from a String when a class can only read from a File.

ie.
generic_class :SomeClass, String do
def getline
...
end

Another wish is for pattern matching:
generic_method :foo, :a, :b :a do ...
where wherever :a occurs it must be the same type so:
foo 4 "a" 4 passes
but
foo "a" 4 4 fails.

Looking at the rdoc some code in that could be very helpful - such as
Contact.adapt.

thanks,
Isaac

P.S. I have an updated version which generates methods instead of
lookup + some extras. Nobody mind if I post it to the ml later(ie no
negative)?


Robert Klemme

12/29/2005 11:07:00 AM

0

Isaac Devine <isaac.devine@gmail.com> wrote:
> On Wed, 28 Dec 2005 23:24:01 +0900
> Florian Groß <florgro@gmail.com> wrote:
>>> I have been hacking away to create a simple library that adds
>>> generics-like qualities to ruby. At the moment you can define
>>> methods with type-matches, defaults if no match and different
>>> number of argument matches.
>>
>> Been there, done that:
>>
>> http://ruby-contract.ruby...
>>
>> New ideas are very welcome.
>>
>
> Thanks! I've quickly looked at the ruby-doc for that. It's seems to
> only be able to specific "contracts" for classes, with method
> signatures as a subset. What my goal for generics is to be able to
> choose what code to execute based on method/class parameter types.
> ie.
> converting :
> def foo(arg)
> if arg.kind_of? String
> puts "it is a string! reverse it! #{arg.reverse}"
> elsif arg.kind_of? Fixnum
> puts "Fixnum! double it! #{2*arg}"
> end
> end
>
> into:
>
> generic_method :foo, String do |arg|
> puts "it is a string! reverse it! #{arg.reverse}"
> end
>
> generic_method :foo, Fixnum do |arg|
> puts "Fixnum! double it! #{2*arg}"
> end

That's not generics but overloading. I'm sorry, but with these things it's
really important to use teminology properly otherwise you'll likely cause a
lot of misunderstandings.

> In the future I would like to be able to extend this to classes as
> well. One implication of this we will be the ability to get rid of
> "adapter" classes when joining heirachys. One example would be adding
> support to reading from a String when a class can only read from a
> File.
>
> ie.
> generic_class :SomeClass, String do
> def getline
> ..
> end

IMHO this is a bad example because you can turn a String into a StringIO
which supports IO like behavior. If some method works on an IO instance it
almost always works on a StringIO, too.

> Another wish is for pattern matching:
> generic_method :foo, :a, :b :a do ...
> where wherever :a occurs it must be the same type so:
> foo 4 "a" 4 passes
> but
> foo "a" 4 4 fails.

Sounds like you wanted to reimplement some features very common with
functional languages in Ruby. Why do you do that?

> P.S. I have an updated version which generates methods instead of
> lookup + some extras. Nobody mind if I post it to the ml later(ie no
> negative)?

If you really intend to go further down that road I suggest you create a
project on rubyforge (or merge with an existing project).

I'm sorry to be so discouraging but this seems like yet another attempt to
retrofit other languages' features to Ruby instead of using it the way it
is.

Kind regards

robert

dblack

12/29/2005 12:05:00 PM

0

Florian Groß

12/29/2005 2:20:00 PM

0

dblack

12/29/2005 3:21:00 PM

0

Florian Groß

12/29/2005 5:22:00 PM

0