Hello!
As I explore Ruby, I like it more and more, but of course more and more
questions arise, as well.
1) It is not clear to me what is the right idiom to use when a module is
used only as a collection of some main (i.e. published) functions,
implemented by other internal (i.e. private) functions... i.e. the Module
is not intended to be included anywhere (module Math could be an
example of what I mean).
Suppose that module M publishes an 'm' function, which is implemented by
'm1', which in turn uses 'm2'.
Having exluded the 'module_function' approach:
module M
def m2
puts "In M2"
end
def m1
m2
end
def m
m1
end
module_function :m
end
since it won't work:
M.m -> mod3.rb:11:in `m': undefined local variable or method `m1' for
M:Module (NameError)
I tried:
module M
def m2
puts "In m2"
end
def m1
m2
end
def M.m
o=Object.new
o.extend self
o.m1
end
end
M.m -> In m2
and:
module M
private
def M.m2
puts "In m2"
end
def M.m1
m2
end
public
def M.m
m1
end
end
M.m -> In m2
Both work, but I feel like none is the right one... The first solution
requires creating and than extending an object, just for the purpose of
having something to which "attach" M's instance methods, and it looks
ugly. The second solution looks more "clean" and maybe I'm just not OO
enough to accept it :-) but IMHO m1 and m2 would "look better" as
instance methods.
So... is there another "right" way to get what I want?
2) In "Programming Ruby", it is said that the global availability of
functions like 'Array', 'open', 'putc', 'sleep', etc., depends on the
fact that such functions are module methods of Kernel, and that Kernel is
included by Object. In fact, 'Kernel.singleton_methods.sort' returns:
['Array', 'Float', 'Integer', ...]
However, also 'Kernel.private_instance_methods.sort' returns:
['Array', 'Float', 'Integer', ...]
and the two sets are almost identical:
irb(main):005:0> Kernel.singleton_methods-Kernel.private_instance_methods
[]
irb(main):006:0> Kernel.private_instance_methods-Kernel.singleton_methods
["remove_instance_variable"]
The functions actually used when called without an explicit receiver are
(of course) the private instance methods:
irb(main):001:0> module Kernel
irb(main):002:1> def sleep
irb(main):003:2> puts "No thanks, I'm not tired"
irb(main):004:2> end
irb(main):005:1> end
nil
irb(main):006:0> sleep
No thanks, I'm not tired
nil
irb(main):007:0> Kernel.sleep
<<press CTRL-C>>
IRB::Abort: abort then interrupt!!
from E:/RUBY/lib/ruby/1.6/irb.rb:79:in `irb_abort'
from E:/RUBY/lib/ruby/1.6/irb.rb:214:in `signal_handle'
from E:/RUBY/lib/ruby/1.6/irb.rb:64:in `start'
from E:/RUBY/lib/ruby/1.6/irb.rb:63:in `call'
from (irb):7:in `sleep'
from (irb):7
So my question is: why are the functions defined as both singletons and
private instance methods? To allow the coexistence of both
'Kernel.function()' and the 'function()' syntaxes? Or to allow
possible redefinitions of the instance methods in terms of the singletons
methods? Or... what else?
Thank you for your help,
Andrea