New newbies Qs on Ruby

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 methodm1’ 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 :slight_smile: but IMHO m1 and m2 would “look better” as
instance methods.

So… is there another “right” way to get what I want?

  1. 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
<>
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:insignal_handle’
from E:/RUBY/lib/ruby/1.6/irb.rb:64:in start' from E:/RUBY/lib/ruby/1.6/irb.rb:63:incall’
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

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 :slight_smile: but IMHO m1 and m2 would “look better” as
instance methods.

So… is there another “right” way to get what I want?

your third is right. you can use def self.m1 instead from what i
understand, though i never do. and self will pick up the module at that
level. that’s how it works ruby allows you to define module/class
methods by prefixing the module/class name and a period. honest
question, how would you want it to work?

-tom

···

On Thu, 2002-09-12 at 02:59, Overnight wrote:

  1. 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
<>
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


tom sawyer, aka transami
transami@transami.net

Hello –

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:
since it won’t work:

M.m → mod3.rb:11:in m': undefined local variable or method m1’ for
M:Module (NameError)

I tried:
[object.extend approach]

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 :slight_smile: but IMHO m1 and m2 would “look better” as
instance methods.

So… is there another “right” way to get what I want?

Actually m1 and m2 are instance methods; the instance of which they
are methods just happens to be an instance of class Module :slight_smile: If you
want to avoid the explicity M. syntax, you can temporarily enter into
the virtual class of M, where (as in all class definitions) the
methods you create are instance methods of instances of the class (M
being the only instance of this particular class).

module M
class << self
private
def m2
puts “In m2”
end

  def m1
m2
  end

  public
  def m
m1
  end
end

end

David

···

On Thu, 12 Sep 2002, Overnight wrote:


David Alan Black | Register for RubyConf 2002!
home: dblack@candle.superlink.net | November 1-3
work: blackdav@shu.edu | Seattle, WA, USA
Web: http://pirate.shu.edu/~blackdav | http://www.rubyconf.com

another solution:

class Module
def module_function_subroutine(*names)
for m in names
module_function m
private_class_method m
end
end
end

module M
def m2() puts “m2” end
def m1() m2 end
def m() m1 end

module_function :m
module_function_subroutine :m1, :m2

end

M.m
M.m1 #=> NameError or NoMethodError
M.m2 #=> NameError or NoMethodError

– Gotoken

···

At Thu, 12 Sep 2002 17:59:50 +0900, Overnight wrote:

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)

In article 1031822816.581.1224.camel@silver, transami@transami.net
says…

So… is there another “right” way to get what I want?
your third is right. you can use def self.m1 instead from what i
understand, though i never do. and self will pick up the module at that
level. that’s how it works ruby allows you to define module/class
methods by prefixing the module/class name and a period. honest
question, how would you want it to work?

Well, any way will do, as long as I have a clear grasp of what’s going on
and of the rationale behind some design choices :slight_smile: I’m exploring Ruby
and in this phase I’m really open-minded, as long as I have an
understanding of the language’s workings and idioms.

It is a fact, however, that my past experiences with Perl, Python and
Visual Basic, have had some (bad?) influence on my personal definition of
what a Module is.

Influenced by such languages which tend to give to ‘module’ the meaning
of “container of functions”, I was tempted to write:

module M
private
def m2
puts “In m2”
end
def m1
m2
end
public
def m
m1
end
end
M.m

i.e., I was tempted to avoid the ‘M.*’ syntax, except when absolutely
needed (to specify the namespace in which m() is defined, in this case).
But… this is just too Perlish or Pythonesque, I’m afraid… I must
upgrade my mind to an OO view :slight_smile:

(warning: what follow is my personal opinion, no flame intended :slight_smile: )

I really like Ruby. Last summer I downloaded Squeak and so I
(re)discovered the beauty of Smalltalk, which I had not used for more
than 10 years (while I was graduating). I was using Python for sysadm and
text processing tasks, and comparing it with Smalltalk convinced me that
it (Python) was too much of a kludge for my personal taste. Not to talk
about the new features introduced by Python 2.2, definitely too
bizantine for me. Someone on comp.lang.pyhton mentioned Ruby, I
downloaded it and… it was what I wanted, kind-of Smalltalk without the
Smalltalk environment, usable both for scripting and quick and dirty one-
liners and for larger projects.

Probably because I’m graduated in Computer Science, I tend to consider
every language as a work of art, and before using it for something
“useful” I spend some/a lot of time to understand it and its design
choices. Under this particular point of view, I find Ruby to be quite
“beautiful”, and I’ll drop Python for it.

There are some things I don’t like, but compared with what I don’t like
in other languages they are not so important. To be honest, I’m not sure
that the freedom in syntax allowed by Ruby promotes readability. If a
line of code is:

funcname a

how do you now if you must read it as:

funcname(a) (where a is a variable)

or

funcname(self.a())

Also I don’t like things that can be written in different manners,
because I think these ambiguities make code less readable. For example a
block may be delimited by ‘do…end’ or by ‘{…}’: I personally prefer
‘{…}’, but when I read code written by others I must remember to also
look for ‘do…end’…

And I still don’t understand why (see my previous posts):

  • aModule.constants behaves differently from aClass.constants (but there
    is a very pragmatic answer here: aClass.constants-
    aClass.superclass.constants will work, while aModule.constants-
    aModule.superclass.constants won’t)

  • module Kernel defines as singleton methods (almost) all of his private
    instance methods

But this are minor things, and all in all I like what I’ve seen so far :-
)

Thank you for your answer, and excuse me for a lengthy reply :slight_smile:

Andrea

···

On Thu, 2002-09-12 at 02:59, Overnight wrote:

another solution:

class Module
def module_function_subroutine(*names)
for m in names
module_function m
private_class_method m
end
end
end

module M
def m2() puts “m2” end
def m1() m2 end
def m() m1 end

module_function :m
module_function_subroutine :m1, :m2

end

M.m
M.m1 #=> NameError or NoMethodError

Yes, it works, but your answer and answers from other members (thanks to
all!) definitely convinced me of one thing: I must think in Ruby, I am
not in PlainProcedureLand anymore :slight_smile:

Andrea

Fri, 13 Sep 2002 06:41:06 +0900, Overnight <NOSPAM_jazz_x@libero.it_NOSPAM> pisze:

i.e., I was tempted to avoid the ‘M.*’ syntax, except when absolutely
needed (to specify the namespace in which m() is defined, in this case).
But… this is just too Perlish or Pythonesque, I’m afraid… I must
upgrade my mind to an OO view :slight_smile:

Let me say that I deliberately avoided reading again the details
of Ruby’s instance / singleton methods, include / extend, . / ::,
where names are looked up, how self is set, and the class / module
hierarchy near Object, Kernel, Module etc.

I know the basics and could learn more if I needed to use Ruby more
in practice. But I wanted to see if they are intuitive enough to
understand them from discussions here, not by reading formal rules
but by observing how they are used.

The result is that I didn’t get them. Either my mind is too influenced
by other languages (mainly functional, I’m not an OO fan) or OO is
a bit unintuitive. Why each language has very different rules for
that metaclass stuff?

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/