a newbie question about main, Object...

S

Sam Sungshik Kong

Hello!

I am trying to understand Ruby's pure OO concept.
As my understanding is limited, my questions might seem silly...;-)

1. In irb, if I type self, it returns main which is type of Object.
self =>main
=>Object
main
NameError: undefined local variable or method `main' for main:Object
from (irb):28
from :0

I understand that main is an instance of type Object.
Why can't I access main directly like main.something?
What *actually* is main?
A global instance?

2. I heard that the top-level functions become methods of Object.
Then am I defining a class (Object)?

If I do the following
print "Hello"
what did I do? Am I in the Object class definition part or outside of
Object?
In other words, is the code <print "Hello"> part of Object?
If not, how is it related to main?

Likewise, if I declare a variable on top-level, is it part of Object?
Of course, it's a global variable.
Is a global variable outside of Object class?
If so, it's not OO...?

Well, I hope I expressed my questions well.

Thanks in advance.

kong
 
J

Joel VanderWerf

Sam said:
1. In irb, if I type self, it returns main which is type of Object.


NameError: undefined local variable or method `main' for main:Object
from (irb):28
from :0

I understand that main is an instance of type Object.
Why can't I access main directly like main.something?
What *actually* is main?
A global instance?

That's a good question.

You could do

$main = self

at the top of your code if you wanted to treat the object as a global
instance. But most of the time, I just forget that this object exists.

IMHO, this object exists primarily so that you can write and call
methods in the top-level scope and then easily migrate them inside a
class or module. A trivial example:

---
def add(x,y)
x+y
end

p add(1,3)
---

---
module Operations
def add(x,y)
x+y
end
end

include Operations

p Operations.add(1,3)
---
 
J

Joel VanderWerf

Joel said:
---
module Operations
def add(x,y)
x+y
end
end

include Operations

p Operations.add(1,3)
---

Oops. This code works, but it's a little confusing. Since I included
Operations, all I needed to do was

p add(1,3)

If I hadn't included Operations, then

p Operations.add(1,3)

would _not_ work, because add is an instance method, not a module
method, of Operations.

Now I've probably only increased the confusion. There are better
explanations in the Pick Axe book:

http://www.ruby-doc.org/docs/ProgrammingRuby
 
T

ts

J> IMHO, this object exists primarily so that you can write and call
J> methods in the top-level scope and then easily migrate them inside a
J> class or module. A trivial example:

The glossary say, about main

: (:)main:))

'((|((<self>))|))' at top level.

Since it can't be without self,
it is a mere ((<instance|Instance>)) of an ((<Object>)) class,
only for being there.
Some ((<singleton methods|Singleton Method>)) are defined
to operate the Object class.

Defined ((<singleton method|Singleton Method>)):

* private
* public
* include




Guy Decoux
 
T

Tore Darell

Hello!

I am trying to understand Ruby's pure OO concept.
As my understanding is limited, my questions might seem silly...;-)

1. In irb, if I type self, it returns main which is type of Object.
NameError: undefined local variable or method `main' for main:Object
from (irb):28
from :0

I understand that main is an instance of type Object.
Why can't I access main directly like main.something?
What *actually* is main?
A global instance?


As I understand it, "main" is an object of class Object that everything
outside of other class definitions belongs to, but it is not bound to
a variable. The name "main" is simply the string returned by this object's
"to_s" (or "inspect") method..

Tore
 
K

Kevin Bullock

2. I heard that the top-level functions become methods of Object.
Then am I defining a class (Object)?

If I do the following
what did I do? Am I in the Object class definition part or outside of
Object?
In other words, is the code <print "Hello"> part of Object?
If not, how is it related to main?

Likewise, if I declare a variable on top-level, is it part of Object?
Of course, it's a global variable.
Is a global variable outside of Object class?
If so, it's not OO...?

If you declare a method at top-level, it is a method of Object. For
example:

irb(main):001:0> Object.instance_methods.include? 'foo'
=> false
irb(main):002:0> def foo; puts 'hello'; end
=> nil
irb(main):003:0> Object.instance_methods.include? 'foo'
=> true
irb(main):004:0> Object.new.foo
hello
=> nil
irb(main):005:0> self.foo
hello
=> nil

If you declare a variable at top-level, its scope depends on how you
declare it. A local variable (e.g. foo = 'foo') should only be scoped
within the current block (or, at top-level, within the top level of the
script or interactive session). That means that other objects and
methods won't be able to access it. Example:

irb(main):001:0> foo = 'foo'
=> "foo"
irb(main):002:0> def hi; puts foo; end
=> nil
irb(main):003:0> hi
NameError: undefined local variable or method `foo' for main:Object
from (irb):2:in `hi'
from (irb):3

If you declare it as an instance variable, it becomes an instance
variable of that "main" object:

irb(main):004:0> @foo = 'foo'
=> "foo"
irb(main):005:0> p Object.new
#<Object:0x4e6f8>
=> nil
irb(main):007:0> p self.inspect
"#<Object:0x37a08 @foo=\"foo\">"
=> nil

If you declare it as a class variable, it becomes a class variable of
Object:

irb(main):008:0> @@foo = 'foo'
=> "foo"
irb(main):012:0> def Object.hi; puts @@foo; end
=> nil
irb(main):013:0> Object.hi
foo
=> nil

Lastly, if you declare it global, it is of course global (any code in
any class or module can access it):

irb(main):015:0> module Demo
irb(main):016:1> class Test
irb(main):017:2> def hi
irb(main):018:3> puts $foo
irb(main):019:3> end
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):022:0> Demo::Test.new.hi
foo
=> nil

I hope that helps to explain matters. This is exactly the behavior I
would expect from the scoping rules given for Ruby.

Pacem in terris / Mir / Shanti / Salaam / Heiwa
Kevin R. Bullock
 
K

Kevin Bullock

This thread brought up an interesting idea in my mind. If one truly
wants to define a top-level method, perhaps you could do this:

irb(main):001:0> class << self
irb(main):002:1> def foo; puts "singleton method of top-level Object
instance"; end
irb(main):003:1> end
=> nil
irb(main):004:0> foo
singleton method of top-level Object instance
=> nil
irb(main):005:0> Object.new.foo
NoMethodError: undefined method `foo' for #<Object:0x4c6dc>
from (irb):5

The usefulness of this depends on what you want a top-level method for.
If you want a globally accessible method, the foregoing approach
doesn't work:

irb(main):006:0> class Demo
irb(main):007:1> def bar; foo; end
irb(main):008:1> end
=> nil
irb(main):009:0> Demo.new.bar
NameError: undefined local variable or method `foo' for #<Demo:0x216e0>
from (irb):7:in `bar'
from (irb):9

But then, globally accessible methods are generally frowned upon in
pure OO design. If, on the other hand, you're hacking out a quick
script to do something useful, and you want a top-level method that
only needs to be accessed at top-level, this works quite well *and*
maintains good information hiding practice.

Just some random thoughts I had. Seems like I may have seen this
before... is this an established idiom?

Pacem in terris / Mir / Shanti / Salaam / Heiwa
Kevin R. Bullock
 
S

Sam Sungshik Kong

Excellent explanation, Kevin!

Kevin, what is the right way to think about a global variable?
In pure OO, there's no real global variable, right?
Then, is it against OO?

Thanks.

kong
 
K

Kevin Bullock

Excellent explanation, Kevin!

Glad I could help.
Kevin, what is the right way to think about a global variable?
In pure OO, there's no real global variable, right?
Then, is it against OO?

There's likely to be differing opinions on this matter. I don't think
it's necessarily against good object-oriented style to have global
variables available in a language. This seems to fit in well with
Ruby's approach to interacting very easily with the surrounding system,
but still having everything be an object. Ruby preserves information
hiding and encapsulation for the general case, as one would expect, and
chooses to also allow some variables to be globally accessible. They're
seldom used and declared differently, which seems to discourage using
them in places they're not meant to be.

There is an argument to be made, though, that allowing global variables
does in fact break information hiding, and I have some affinity for
that argument as well. But in practice, having globals is useful for
covering Perl's problem space with Ruby, even if you never use them
when covering Java's problem space.

Pacem in terris / Mir / Shanti / Salaam / Heiwa
Kevin R. Bullock
 
G

George Ogata

Kevin Bullock said:
Just some random thoughts I had. Seems like I may have seen this
before... is this an established idiom?

There was a time when toplevel defs were *private* instance methods of
Object. The pickaxe says this anyway. I see nothing in the
Changelogs about any intentional change, so my guess is it's a bug.
Gurus?
 
D

daz

Kevin said:
This thread brought up an interesting idea in my mind. If one truly
wants to define a top-level method, perhaps you could do this:

irb(main):001:0> class << self
irb(main):002:1> def foo; puts "singleton method of top-level Object
instance"; end
irb(main):003:1> end
=> nil
irb(main):004:0> foo
singleton method of top-level Object instance
=> nil
irb(main):005:0> Object.new.foo
NoMethodError: undefined method `foo' for #<Object:0x4c6dc>
from (irb):5

The usefulness of this depends on what you want a top-level method for.
If you want a globally accessible method, the foregoing approach
doesn't work:

irb(main):006:0> class Demo
irb(main):007:1> def bar; foo; end
irb(main):008:1> end
=> nil
irb(main):009:0> Demo.new.bar
NameError: undefined local variable or method `foo' for #<Demo:0x216e0>
from (irb):7:in `bar'
from (irb):9

But then, globally accessible methods are generally frowned upon in
pure OO design. If, on the other hand, you're hacking out a quick
script to do something useful, and you want a top-level method that
only needs to be accessed at top-level, this works quite well *and*
maintains good information hiding practice.

[...] is this an established idiom?

Not one that I've seen a lot of.

This script could be useful for self-hypnosis :)

def self.roo
puts "*** (singleton roo) [#{self}] (#{self.class} instance) ***"
super
end

class Object
def roo
puts "*** ( object roo) [#{self}] (#{self.class} instance) ***"
super
end
end

module Kernel
def roo
puts "*** ( kernel roo) [#{self}] (#{self.class} instance) ***"
end
end

roo

#=> *** (singleton roo) [main] (Object instance) ***
#=> *** ( object roo) [main] (Object instance) ***
#=> *** ( kernel roo) [main] (Object instance) ***


daz
 
T

Tim Sutherland

There was a time when toplevel defs were *private* instance methods of
Object. The pickaxe says this anyway. I see nothing in the
Changelogs about any intentional change, so my guess is it's a bug.
Gurus?

They still are. This was just an irb thing.

$ cat > foo.rb
def hello
puts("Hello World")
end

"blah".hello
^D
$ ruby foo.rb
foo.rb:5: private method `hello' called for "blah":String (NoMethodError)

But in irb

irb(main):001:0> def hello
irb(main):002:1> puts("Hello World")
irb(main):003:1> end
=> nil
irb(main):004:0> "blah".hello
Hello World
=> nil
 
W

WATANABE Hirofumi

They still are. This was just an irb thing.

$ cat > foo.rb
def hello
puts("Hello World")
end

"blah".hello
^D
$ ruby foo.rb
foo.rb:5: private method `hello' called for "blah":String (NoMethodError)

But in irb

irb(main):001:0> def hello
irb(main):002:1> puts("Hello World")
irb(main):003:1> end
=> nil
irb(main):004:0> "blah".hello
Hello World
=> nil
 

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

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top