Creating modules

B

benjohn

I am dynamically creating modules [1]. I would like to be able to add
methods and constants to the module using the "normal" notation:

module MyModule
def a_method; 'wibble'; end
end

But the module doesn't have an constant associated with it, so I'm
getting an error from...

class MyModuleClass < Module
def initialize(a_constant_to_go_in_module)
module self
K = a_constant_to_go_in_module
def a_method; end
...
end
end
end

Is there a way to do this, or do I have to start using the define_method
and const_set methods?

Cheers,
Benjohn

[1] These modules encapulate the behaviour of different types of
message. There are quite a few types of message; while all different,
they're sufficiently similar that the differences can be described in a
table. It's easy to think of a class of types of message: a given
message is an instance of a type of message.
 
D

David Vallner

--------------enigCDA118CC99E78AEB21E125BE
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

But the module doesn't have an constant associated with it, so I'm
getting an error from...
=20
class MyModuleClass < Module
def initialize(a_constant_to_go_in_module)
module self
K =3D a_constant_to_go_in_module
def a_method; end
...
end
end
end
=20
Is there a way to do this, or do I have to start using the define_metho= d
and const_set methods?
=20

See David Black's post in the "dynamic include" thread. The module
declaration creates a new independent scope, so you have to use the meta
methods.

David Vallner


--------------enigCDA118CC99E78AEB21E125BE
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFIOYny6MhrS8astoRAv3uAJ0aj6+eOKrz6xPPPi+qN6GX78Y74gCfbiqr
IPbIXlwpsALzzu1Wypd63aM=
=6N3e
-----END PGP SIGNATURE-----

--------------enigCDA118CC99E78AEB21E125BE--
 
B

benjohn

David Vallner:
See David Black's post in the "dynamic include" thread. The module
declaration creates a new independent scope, so you have to use the meta
methods.

Thanks, I'll take a look...
 
B

benjohn

I wrote before about the modules I'm trying to build on the fly. I'm
going to describe it a bit more and see if anyone has a thought about
what I should be doing here, because I'm not making much ground. [Using
modules was my latest foray in the direction of another approach, but I
think I've given up on that avenue]

What I have are messages and parameters. I'll concentrate on parameters.

Parameters - I have instances of a parameter. Each parameter is an
instance of a type of parameter.

There are about 20 known types of parameter. I must also support unknown
types of parameter (which I will generate on the fly and furnish with
minimal generic behaviour). The known parameters fall in to two groups:
those that have a simple encoding and those with more complex encoding.
To sumarise, the types of parameter have a hierarchy:

ParameterType
UnknownParamerType < ParameterType
KnownParameterType < ParameterType
SimpleParameterType < KnownParameterType
ComplexParameterType < KnownParameterType

Remember that instances of these parameter types are not actual
parameters, they are the classes that parameters instances fall in to.

At the moment, I have a sepererate class for Parameter. Instances of
this delegate to a ParameterType instance. This is annoying me though:
it seems more complex than it ought to be.

I've tried quite a few approaches to putting all this together, but
nothing seems to fit the problem very well.

Any thoughts? Sorry if the above isn't very clear!

Cheers,
Benjohn Barnes

p.s. I think this lends some support to prototype based information models.
 
L

Luke Stark

You may create singleton methods like so:

foo =3D MyThing.new

def foo.do_stuff
"code"
end

But I cannot seem to grock the syntax that would allow me to name the
method from a variable. Such as:

foo =3D MyThing.new
bar =3D "do_stuff"
def foo.%{#{bar}} #This is totally wrong I think.=20
"code"
end

Any suggestions? I'm starting to get a spinning head. :)

To be clear, I want to create a singleton method on the instance of
MyThing, not add the method to the MyThing class.

This is mentioned here:

http://www.rubyist.net/~slagell/ruby/singletonmethods.html

but I'd like to do it dynamically.

Many thanks!

-L
 
J

Jan Svitok

You may create singleton methods like so:

foo = MyThing.new

def foo.do_stuff
"code"
end

But I cannot seem to grock the syntax that would allow me to name the
method from a variable. Such as:

foo = MyThing.new
bar = "do_stuff"
def foo.%{#{bar}} #This is totally wrong I think.
"code"
end

Any suggestions? I'm starting to get a spinning head. :)

To be clear, I want to create a singleton method on the instance of
MyThing, not add the method to the MyThing class.

This is mentioned here:

http://www.rubyist.net/~slagell/ruby/singletonmethods.html

but I'd like to do it dynamically.

Many thanks!

foo = Object.new

def foo.bar
"bar"
end

meth = "baz"
eval <<-EOF
def foo.#{meth} ; "#{meth}" ; end
EOF

meth = "bax"
foo.instance_eval <<-EOF
def #{meth} ; "#{meth}" ; end
EOF

puts foo.bar
puts foo.baz
puts foo.bax
 
J

Jean Helou

class MyThing; end
f=MyThing.new
f.instance_eval do
class << self
define_method :test {puts "test"}
end
end

jean
 
J

Jean Helou

However this will define the given method for all new instances of
obj.class (MyThing in my example) which are created after this code is
executed, which is not what the OP seemed to want.

jean

ps: in my example :test can be a variable and String.to_sym is your friend.
 
B

Bruno Michel

Martin Coxall a écrit :
I'll have one more go. This time I'll get it right. ;p

obj.class.instance_eval do
define_method:)method_name) do |*args|
# Method goes here
end
end

N.B. this actually works this time, because I tried it.

Regards,

Martin

Hi,

You can use class_eval, or better no *eval function :

$ cat my_thing.rb
#!/usr/bin/env ruby

class MyThing; end
foo = MyThing.new

class << foo
bar = "do_stuff"
define_method(bar) { "code" }
end

puts foo.do_stuff

$ ruby my_thing.rb
code
 
L

Luke Stark

Jean,

Hmm. This looks close, but the :test in your example can only be a
variable that has been defined within the instance_eval...and I need to
pass one from outside.=20

The others run, but add the method to the class, rather than the
instance of that class.

I'm sure there's a simple way. I just can't see it.

-L
-----Original Message-----
From: Jean Helou [mailto:[email protected]]
Sent: Monday, October 02, 2006 9:41 AM
To: ruby-talk ML
Subject: Re: Creating dynamically named singleton methods. Syntax
question.
=20
However this will define the given method for all new instances of
obj.class (MyThing in my example) which are created after this code is
executed, which is not what the OP seemed to want.
=20
jean
=20
ps: in my example :test can be a variable and String.to_sym is your
friend.
=20
I'll have one more go. This time I'll get it right. ;p

obj.class.instance_eval do
define_method:)method_name) do |*args|
# Method goes here
end
end

N.B. this actually works this time, because I tried it.

Regards,

Martin
 
J

Jean Helou

this seems to work

$ irb
irb(main):001:0> o=Object.new
=> #<Object:0x100e3128>
irb(main):002:0> s="test"
=> "test"
irb(main):003:0> sym=s.to_sym
=> :test
irb(main):004:0> o.instance_eval do
irb(main):005:1* puts s
irb(main):006:1> klass=class<<self;self;end
irb(main):007:1> klass.send:)define_method,sym){puts "#{s}"}
irb(main):008:1> end
test
=> #<Proc:0x003df7d8@(irb):7>
irb(main):009:0> o.test
test
=> nil


Jean,

Hmm. This looks close, but the :test in your example can only be a
variable that has been defined within the instance_eval...and I need to
pass one from outside.

The others run, but add the method to the class, rather than the
instance of that class.

I'm sure there's a simple way. I just can't see it.

-L
-----Original Message-----
From: Jean Helou [mailto:[email protected]]
Sent: Monday, October 02, 2006 9:41 AM
To: ruby-talk ML
Subject: Re: Creating dynamically named singleton methods. Syntax
question.

However this will define the given method for all new instances of
obj.class (MyThing in my example) which are created after this code is
executed, which is not what the OP seemed to want.

jean

ps: in my example :test can be a variable and String.to_sym is your
friend.

You may create singleton methods like so:



I'll have one more go. This time I'll get it right. ;p

obj.class.instance_eval do
define_method:)method_name) do |*args|
# Method goes here
end
end

N.B. this actually works this time, because I tried it.

Regards,

Martin
 
E

Eero Saynatkari

--R+Rs1qz93vBJxC1z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

I wrote before about the modules I'm trying to build on the fly. I'm
going to describe it a bit more and see if anyone has a thought about
what I should be doing here, because I'm not making much ground. [Using
modules was my latest foray in the direction of another approach, but I
think I've given up on that avenue]

Yes, I think the problem is that this is way overcomplicated. Earlier
you were *subclassing* module which rarely makes sense.
What I have are messages and parameters. I'll concentrate on parameters.
=20
Parameters - I have instances of a parameter. Each parameter is an
instance of a type of parameter.
=20
There are about 20 known types of parameter. I must also support unknown
types of parameter (which I will generate on the fly and furnish with
minimal generic behaviour). The known parameters fall in to two groups:
those that have a simple encoding and those with more complex encoding.
To sumarise, the types of parameter have a hierarchy:
=20
ParameterType
UnknownParamerType < ParameterType
KnownParameterType < ParameterType
SimpleParameterType < KnownParameterType
ComplexParameterType < KnownParameterType
=20
Remember that instances of these parameter types are not actual
parameters, they are the classes that parameters instances fall in to.

Does this mean that
=20
type =3D SomeParameterType.new
parameter_of_type =3D type.new=20

--and if so, why? Classes are there for a reason :)

Or do you mean that each Type contains metadata for parameters
of its type?
At the moment, I have a sepererate class for Parameter. Instances of
this delegate to a ParameterType instance. This is annoying me though:
it seems more complex than it ought to be.
=20
I've tried quite a few approaches to putting all this together, but
nothing seems to fit the problem very well.
=20
Any thoughts? Sorry if the above isn't very clear!

I think your problem comes from trying to (if I understand correctly)
separate Parameters and ParameterTypes.

I do not pretend to understand the problem domain but I do think you need=
=20
to go back to basics and just implement the system traditional OO. If a
parameter type has behaviour differing from its siblings, define it a
separate class.=20

class Parameter; end
class UnknownParameter < Parameter; end
class KnownParameter < Parameter; end
class SomeParameterType < KnownParameter; end

# Aha, got a SomeParameter
my_param =3D SomeParameter.new arguments, go, here
Cheers,
Benjohn Barnes
=20
p.s. I think this lends some support to prototype based information model=
s.

Prototyping is based on cloning *objects*, not classes. If you were to
take this approach, you would simply a parameter object which exhibited
the correct behaviour for its type. Instantiating new parameter objects
would happen by #cloning the prototype and changing values as necessary.
The prototype object could be constructed either by instantiating a
class or then in the 'true' style by defining singleton methods on a
plain Object.

--R+Rs1qz93vBJxC1z
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (FreeBSD)

iD8DBQFFIS6I7Nh7RM4TrhIRAkfeAKC7JC0OKbO7DmNqvkfJV0dwnbbqYQCfSgNP
f+gGYJRv2FKVagPbCExM8BE=
=JyJn
-----END PGP SIGNATURE-----

--R+Rs1qz93vBJxC1z--
 
L

Logan Capaldo

I am dynamically creating modules [1]. I would like to be able to add
methods and constants to the module using the "normal" notation:

module MyModule
def a_method; 'wibble'; end
end

But the module doesn't have an constant associated with it, so I'm
getting an error from...

class MyModuleClass < Module
def initialize(a_constant_to_go_in_module)
module self
K = a_constant_to_go_in_module
def a_method; end
...
end
end
end

Is there a way to do this, or do I have to start using the define_method
and const_set methods?
No, well at least not if you know the method name before hand.

def initialize(a_constant_to_go_in_module)
self.module_eval do
K = a_constant_to_go_in_module
def a_method; 'wibble'; end
end
end
Cheers,
Benjohn

[1] These modules encapulate the behaviour of different types of
message. There are quite a few types of message; while all different,
they're sufficiently similar that the differences can be described in a
table. It's easy to think of a class of types of message: a given
message is an instance of a type of message.
 
L

Luke Stark

Thank you Jean, that works wonderfully.

Thank you everyone else for your input as well.

-L
-----Original Message-----
From: Jean Helou [mailto:[email protected]]
Sent: Monday, October 02, 2006 10:59 AM
To: ruby-talk ML
Subject: Re: Creating dynamically named singleton methods. Syntax
question.
=20
this seems to work
=20
$ irb
irb(main):001:0> o=3DObject.new
=3D> #<Object:0x100e3128>
irb(main):002:0> s=3D"test"
=3D> "test"
irb(main):003:0> sym=3Ds.to_sym
=3D> :test
irb(main):004:0> o.instance_eval do
irb(main):005:1* puts s
irb(main):006:1> klass=3Dclass<<self;self;end
irb(main):007:1> klass.send:)define_method,sym){puts "#{s}"}
irb(main):008:1> end
test
=3D> #<Proc:0x003df7d8@(irb):7>
irb(main):009:0> o.test
test
=3D> nil
=20
=20
Jean,

Hmm. This looks close, but the :test in your example can only be a
variable that has been defined within the instance_eval...and I need to
pass one from outside.

The others run, but add the method to the class, rather than the
instance of that class.

I'm sure there's a simple way. I just can't see it.

-L
-----Original Message-----
From: Jean Helou [mailto:[email protected]]
Sent: Monday, October 02, 2006 9:41 AM
To: ruby-talk ML
Subject: Re: Creating dynamically named singleton methods. Syntax
question.

However this will define the given method for all new instances of
obj.class (MyThing in my example) which are created after this code is
executed, which is not what the OP seemed to want.

jean

ps: in my example :test can be a variable and String.to_sym is your
friend.


You may create singleton methods like so:



I'll have one more go. This time I'll get it right. ;p

obj.class.instance_eval do
define_method:)method_name) do |*args|
# Method goes here
end
end

N.B. this actually works this time, because I tried it.

Regards,

Martin
 
B

benjohn

I am dynamically creating modules [1]. I would like to be able to add
methods and constants to the module using the "normal" notation:

module MyModule
def a_method; 'wibble'; end
end

But the module doesn't have an constant associated with it, so I'm
getting an error from...

class MyModuleClass < Module
def initialize(a_constant_to_go_in_module)
module self
K = a_constant_to_go_in_module
def a_method; end
...
end
end
end

Is there a way to do this, or do I have to start using the
define_method
and const_set methods?
No, well at least not if you know the method name before hand.

I presume you meant "... not if you _don't_ know the method name ..."?
def initialize(a_constant_to_go_in_module)
self.module_eval do
K = a_constant_to_go_in_module
def a_method; 'wibble'; end
end
end

Ah! I think that's exactly what I want :) Thanks, I'll give it a try :)
 
B

benjohn

I wrote before about the modules I'm trying to build on the fly. I'm
going to describe it a bit more and see if anyone has a thought about
what I should be doing here, because I'm not making much ground.
[Using
modules was my latest foray in the direction of another approach, but
I
think I've given up on that avenue]

Yes, I think the problem is that this is way overcomplicated. Earlier
you were *subclassing* module which rarely makes sense.

:) I had a try at sub classing Class for a while (I'm still not sure if
that actually makes sense, I _think_ it does), but Ruby doesn't seem to
like that:

irb(main):001:0> class ParameterClass < Class
irb(main):002:1> end
TypeError: can't make subclass of Class
from (irb):1

*snip*
Does this mean that

type = SomeParameterType.new
parameter_of_type = type.new

--and if so, why? Classes are there for a reason :)

Yes, that's what I mean. There are a large number of parameter types. I
don't want to describe all of them individually as classes; in fact, I'm
unable to describe them all individually because some of the types of
parameter will not be known about until run time.

I know there are a lot of ways of skinning this. I know that I could
build up each parameter individually, and forget about trying to
describe the classes they have in common (even though I don't want to
describe them all individually)...

The current solution has objects representing the different types of
parameter, which is a start. As those objects are conceptually identical
to classes though (in my brain anyway), I'd like them to actually _be_
classes. I feel that doing so would be concordant with Ruby's object
model, and should lead to an elegant solution.
Or do you mean that each Type contains metadata for parameters
of its type?

:) Metadata?

The parameters fall in to a large number of different parameter types.
There is common behaviour between each parameter of a given type. Some
of the parameter types I want to define (but very briefly, without
needing to do...:

class yet_another_parameter;
...
end

...and some I may encounter "on the fly". The types themselves fall in
to a small number of seperate parameter type types (yuck).

*snip*

I also need the parameter_types to exist as objects in their own right;
I need to be able to pass them about them in the program, store them in
tables, and look them up.
Prototyping is based on cloning *objects*, not classes. If you were to
take this approach, you would simply a parameter object which exhibited
the correct behaviour for its type. Instantiating new parameter objects
would happen by #cloning the prototype and changing values as necessary.
The prototype object could be constructed either by instantiating a
class or then in the 'true' style by defining singleton methods on a
plain Object.

*nods* I think that aligns with what I understood of prototype systems.
The reason I lean towards that approach is because, having done away
with classes, you don't need to decide if something is a class or not. I
would imagine that having a single uniform concept would be a lot
easier. You don't need to think through whether something is a lot like
a class, but isn't really a class because...

However, another post in this thread has given me the hope that if I
have another try at this, I'll be able to come up with a good solution
:)

Thanks for the help,
Cheers,
Benj
 
B

benjohn

I presume you meant "... not if you _don't_ know the method name ..."?

Ah - I get you - you were confirming the first part of my sentence, and
rejecting the latter. :) Right! Thanks.
 
B

benjohn

def initialize(a_constant_to_go_in_module)
Ah! I think that's exactly what I want :) Thanks, I'll give it a try :)

So, I've been having an experiment, and here's what I've found so far...

irb(main):001:0> class MyModule < Module
irb(main):002:1> def initialize(k)
irb(main):003:2> module_eval {K=k}
irb(main):004:2> end
irb(main):005:1> end
SyntaxError: compile error
(irb):3: dynamic constant assignment
module_eval {K=k}
^
from (irb):5

But I can do...

irb(main):001:0> x=10
=> 10
irb(main):002:0> m=Module.new
=> #<Module:0xb73ee938>
irb(main):003:0> m.module_eval {K=x}
=> 10

However, if I then try...

irb(main):004:0> m::K
NameError: uninitialized constant #<Module:0xb73ee938>::K
from (irb):4
irb(main):005:0> m.constants
=> []

But I can do...

irb(main):006:0> m.const_get:)X)
NameError: uninitialized constant #<Module:0xb73ee938>::X
from (irb):6:in `const_get'
from (irb):6
irb(main):007:0> m.const_get:)K)
=> 10

!? Huh? I guess this is something to do with constants being looked up
in a global symbol pool?

Going back to trying to define a sub class of modules...

irb(main):009:0> vishnu in new_try# irb
irb(main):001:0> class MyModule < Module
irb(main):002:1> def initialize(x)
irb(main):003:2> super()
irb(main):004:2> module_eval do
irb(main):005:3* def f; x; end
irb(main):006:3> def self.g; x*x; end
irb(main):007:3> end
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> m=MyModule.new(10)
=> #<MyModule:0xb73ded44>
irb(main):011:0> m.g
NameError: undefined local variable or method `x' for
#<MyModule:0xb73ded44>
from (irb):6:in `g'
from (irb):11
irb(main):012:0> Object.new.extend(m).f
NameError: undefined local variable or method `x' for #<Object:0xb73d6270>
from (irb):5:in `f'
from (irb):12
irb(main):013:0>

...Which is a bit of a pitty.

I also briefly dabled with...

irb(main):018:0> class ParameterClass < Class
irb(main):019:1> end
TypeError: can't make subclass of Class
from (irb):18
irb(main):020:0>

And turned away from that avenue.

I think I need a better idea of what is and isn't possible here. I think
my understanding of the dark secrets is very little; I was hoping I'd
get away with that though, as I generally have with Ruby until now :)

Cheers,
Benjohn
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top