Everything is a object?

T

tsela.cg

Ruby's a pretty clever girl. ;)

True, but maybe not advisable for beginners. We don't want to go into
the whole shadowing and "class vs. self.class" business, when Jamal is
already having difficulties with the basics.

Christophe.
 
J

James Edward Gray II

No. "attr_accessor" only defines two instance methods within the class
you're using it in, which allow @var (which is a private instance
variable) to be accessible from outside its object. In other words,

class SomeClass

attr_accessor :var

end

is exactly equivalent to:

class SomeClass

def var
@var
end

def var=(param)
@var = param
end
end

Not "exactly equivalent." It also silences the warning:

$ ruby -we 'class Test; def var; @var; end; end; p Test.new.var'
-e:1: warning: instance variable @var not initialized
nil
$ ruby -we 'class Test; attr_reader :var; end; p Test.new.var'
nil

James Edward Gray II
 
P

Phrogz

That made me confused a little bit, How can nil be a class? and then a
method in object base class (nil?)

Slim:~ gkistner$ irb

irb(main):001:0> a = nil
=> nil

irb(main):002:0> a.class
=> NilClass

irb(main):003:0> nil.class
=> NilClass

irb(main):008:0> NilClass.instance_methods(false)
=> ["to_s", "|", "to_f", "to_a", "&", "^", "nil?", "to_i",
"inspect"]

Just like "true" is the literal way to express an instance of the
TrueClass and "[]" is the literal way to express an instance of the
Array class, "nil" is the literal way to express an instance of the
NilClass. That class has methods, like any other. One of those methods
is named "nil?". (Not that it makes much difference, but note that
"nil?" is a different name from "nil"; the question mark is part of
the name.)

I say that it doesn't make much difference because you can have method
names that are the same as a built-in literal. For example:

irb(main):001:0> class Foo
irb(main):002:1> def true
irb(main):003:2> "maybe"
irb(main):004:2> end
irb(main):005:1> end
=> nil

irb(main):006:0> f = Foo.new
=> #<Foo:0x3847bc>

irb(main):007:0> puts f.true
maybe
=> nil

Heck, lots of built-in classes have a method named "[]", usually used
for accessing methods. Indeed, the Array class, which can be
instantiated by the literal [], is the primary example of it. So if
you write:

irb(main):008:0> [][]
ArgumentError: wrong number of arguments (0 for 1)
from (irb):8:in `[]'
from (irb):8

....what's going on is the first [] instantiate a new array instance,
and the second [] call the "[]" method on them...which requires a
single argument, hence the error.

irb(main):009:0> [ 'a', 'b', 'c', 'd' ][ 2 ]
=> "c"
 
B

Brian Candler

So until I assign something to it, the interpreter would know nothing
about what object it is.

No, it's stronger than that.

If you don't assign something to a local variable, then the interpreter
assumes you're not talking about a local variable at all, but a method call.

foo # 1. interpreted as 'self.foo' or equivalently 'foo()'
foo.bar # 2. interpreted as 'self.foo.bar' or 'foo().bar()'

foo = "x"

foo # 3. now foo is a local variable. This is an expression
# whose value is the objected refered to by foo.
# i.e. the string "x"
foo.bar # 4. invokes 'bar' method on the object refered to by 'foo'

That's because both method names and local variable names fall into the same
namespace (alphanumeric names starting with lower case). There's no "$" to
distinguish a variable from a method as there is in Perl or PHP.

Is it a bit clearer now why it's necessary to assign to a variable before
it's treated as a variable?
When I write attributes in my code:
attr_assoccer :var

I assume > then < the interpreter knows only that @var is a object (base
class)?

That's something else. You've defined two methods in your class, 'var' and
'var=', which read and assign to instance variable @var respectively.

local variables are just scratch space on the stack. They are not instance
variables on an object.

Brian.
 
B

Brian Candler

That made me confused a little bit, How can nil be a class? and then a
method in object base class (nil?)

nil is an instance (the only instance) of class NilClass.

irb(main):001:0> nil.class
=> NilClass
irb(main):002:0> nil.class.ancestors
=> [NilClass, Object, Kernel]
 
T

tsela.cg

They have plenty, but they don't have something like defined?, they have
functions that act as defined? keyword.

So then just tread "defined?" as a function. It's just not a method.
Great example :D I love it :D

Thanks :) .
Well someone should know her before me, to tell me about her, so
basically someone knows about her?

Yes, but not you, and if you follow the analogy from the examples, in
this case you were Ruby :) .
That made me confused a little bit, How can nil be a class?

It's not a class, it's an object. And like any object, it has a class,
called NilClass.

and then a
method in object base class (nil?)

"nil?" is a separate method (the question mark is part of the name, so
"nil" and "nil?" refer to different things), which is defined in
Object (what you call the object base class) to return false, and
overridden in NilClass, to return true. Just try it in irb:

a = Object.new
a.nil?
=> false
nil.nil?
=> true

You are actually completely free to define your own class with a nil?
method returning true, although I wouldn't know why you'd want to do
that.

class SomeNilClass
def nil?
true
end
end

a = SomeNilClass.new
a.nil?
=> true

Christophe.
 
T

tsela.cg

Not "exactly equivalent." It also silences the warning:

$ ruby -we 'class Test; def var; @var; end; end; p Test.new.var'
-e:1: warning: instance variable @var not initialized
nil
$ ruby -we 'class Test; attr_reader :var; end; p Test.new.var'
nil

I didn't know about that one. Thanks.

Also, thanks for pointing out the global variables, I had forgotten
about them :) .

Christophe.
 
J

Jamal Soueidan

It has been long topic now, and very helpful, I must admit I really love
the Ruby Community, such Community is hard to find other places :)

I want to thanks everyone very much :)

------------------------------------------

I think now I understand completely why the following code below is
throwing exception:

puts myvar
# register.rb:1: undefined local variable or method 'myvar' for
main:Object

Ruby don't know what "myvar" is, it could not find any local variable
with that name, or any method in the main:Object (base class)

------------------------------------------

The code below would not throw any exception:
puts @myvar
# nil

Ruby already know whatever start with @ would be instance of something,
if not then it would still be nil object, means false.

puts @myvar.class.to_s
# NilClass

puts @myvar="string".class.to_s
# String

---------------------

The Accessors only provide you with the set and get properties similar
to other languages, when you declare something like this:

attr_accessor :myvar

You would have an instance of nil object.

class A
attr_accessor :myvar
end

a = A.new
p a.myvar.class.to_s
# NilClass

p a.myvar=2.class.to_s
# Fixnum

p a.myvar='string'.class.to_s
# String

---------------------

Why does Ruby treat @myvar different from myvar?
Posted by unknown (Guest) on 04.04.2007 15:30
Exactly why it does that with instance variables and not with local variables
I don't know, but they are used in different enough ways that the difference
should not be bothersome.

The answer:
 
G

Gary Wright

It has been long topic now, and very helpful, I must admit I really
love
the Ruby Community, such Community is hard to find other places :)

I want to thanks everyone very much :)

It looks like things are a lot clearer for you now. Just a couple
comments on your summary:
The code below would not throw any exception:
puts @myvar
# nil

Ruby already know whatever start with @ would be instance of
something,
if not then it would still be nil object, means false.


Start a brand new session of IRB and try:

irb> instance_variables
=> []
irb> @alpha
=> nil
irb> instance_variables
=> ["@alpha"]
irb> @beta = 42
=> 42
irb> instance_variables
=> ["@alpha", "@beta"]
irb> instance_variable_set("@gamma", 'foo')
=> "foo"
irb> instance_variables
=> ["@alpha", "@beta", "@gamma"]

Instance variables come into existence when
1) they appear on the left side of an assignment, in which case
they are
initialized to the value on the right hand side of the assignment
2) when they are referenced in an expression, in which case they are
initialized with a reference to the nil object.
3) when they are set via a call to instance_variable_set()
The Accessors only provide you with the set and get properties similar
to other languages, when you declare something like this:
attr_accessor :myvar
You would have an instance of nil object.

This is a bit misleading. There is one and *only* one instance of
NilClass.
So it would be better to say:

You would have a reference to *the* nil object, which is an instance
of NilClass (the *only* instance).

All reference to 'nil' are references to the *same* object:

@a # force @a to exist
@b # force @b to exist

@a.object_id # 4
@b.object_id # 4
nil.object_id # 4

@a.equal?(nil) # true
@b.equal?(nil) # true
nil.equal?(nil) # true

I think the key thing to remember is that 'nil' is not a special
value that
indicates 'no object'. Instead it is a special object that acts as a
sentinel.
There are a number of Ruby conventions that allow nil to act as a
powerful and
useful sentinel:

1) instance variables and global variables default to reference
the nil object.
2) The literal 'nil' always references the same object, the nil
object.
3) There is no way to create additional instances of NilClass.
4) All objects respond to the method: 'nil?'
5) The nil object is the *only* object that responds with 'true'
to 'nil?'.
All other objects respond with 'false'.
6) In a boolean context, 'nil' is considered false.

These properties enable such idioms as:

@foo ||= 'default'
@bar = first_choice || second_choice || third_choice

Ruby's dynamic typing allows 'nil' to be used as a convenient
sentinel value for
many methods. For example 'getc' returns the next byte from an IO
stream as
an instance of Fixnum but if the end of the stream is encountered nil
is returned
instead of a special sentinel instance of Fixnum (e.g. -1 as in the C
programming
language).

Gary Wright
 
B

Brian Candler

puts @myvar.class.to_s
# NilClass

puts does an implicit to_s on anything you pass to it, so you don't actually
need to do that explicitly.
puts @myvar="string".class.to_s
# String

Careful here. This is the same as

puts @myvar=("string".class.to_s)

i.e. you are assigning "String" to @myvar, not "string".
p a.myvar=2.class.to_s
# Fixnum

Again, here the @myvar instance variable of 'a' now contains string "Fixnum"

Regards,

Brian.
 
B

Booker C. Bense

Ruby understand that everything start with @ is a object, either
reference or a type.

like in other language

@var = &reference
@var = object

when I type it

if var.nil?

var is unknown?

it's not variable, neither object? what is it? nobody knows, throw
exception to the bad coder :p

Ruby variables aren't quite what you expect. They are merely
labels that point to existing objects, they have no inhernet
existance in and of themselves. Ruby will "autocreate" objects
along the way, but IMHO it requires thinking about variables in
a much different way that most other languages use the term
variables.

Personally, I think this is a least an interesting if not good
thing. It requires that you think in different ways about how
variable work.

The problems you are having is that you are making method
calls on non-existant objects. It's like handing a NULL pointer
in C to a function that expects a pointer.

_ Booker C. Bense
 
D

Devin Mullins

Jamal said:
I thought keywords are class, def, end, which mean something to the
compiler only.

http://www.google.com/search?q=ruby+keywords

The first result is comically direct.
I did not think there would be something that behaved like a method
"defined?" which would be keyword?

Why not just make it a global method, put it in a module so nobody is
confused about that, because it looks like a method to me :)

The reason why not is that when calling methods, Ruby always evaluates
the arguments first.[1] So saying `defined? blahblah` would fail,
because Ruby would try to evaluate blahblah, not find a blahblah method,
and raise a NoMethodError.

Now, you *could* make a defined method that took a String instead of a
bare word, e.g.:
def str_defined?(str) # cheap & ugly implementation
eval "defined?(#{str})"
# if you don't want to use defined? there are other hooks available:
# constants, local_variables, instance_variables, class_variables,
# global_variables
# Those guys *are* methods, magically defined by the interpreter.
end
str_defined? "blahblah"

There are method/keyword parallels in Ruby like this -- define_method vs
def, alias_method vs alias, etc.

You could even use blocks to make something that looked like:
is_defined? { blahblah }
But that's very much insane.
Ruby already know whatever start with @ would be instance of
something, if not then it would still be nil object, means false.
"instance variable" does not mean "instance of something," but
explaining what is *does* mean would mean a rather long side-wind into OOP.
Why does Ruby treat @myvar different from myvar?
BTW, you can emulate the @myvar way:
def method_missing(sym, *a, &b)
(!a.empty? || b) ? super : nil
end

a #=> nil
a = 5
a #=> 5

But, like, don't do that.

Devin

[1] This differs from other languages like Lisp and Io -- it probably
comes from its C heritage.
if a.nil?
p 'thanks';
end

class You
def self.method_missing(sym) puts "#{self}'re #{sym}." end
end
You.welcome
 
J

Jamal Soueidan

Gary said:
On Apr 4, 2007, at 2:49 PM, Jamal Soueidan wrote:

Thanks for your comment, now I understand that all the unused instance
variable would reference to the same object until they come into
existence:

1. by assigement.
2. by reference (as default to nil object)
3. by using the object method instance_variable_set()

puts does an implicit to_s on anything you pass to it, so you don't actually
need to do that explicitly.

Thanks, now I know :)
Careful here. This is the same as

puts @myvar=("string".class.to_s)

True,
puts "string".class

-----------------------------------------

Thanks for the other replies :D

Now the question is,

When does the instance variable holds the object itself?

class A; end;

@one = A.new
@two = A.new

p @one.object_id
p @one_object_id
# 21103660
# 21103640

Two different objects, even if they were the same.

How does all the nil instance variable reference to the same object?
 
G

Gary Wright

When does the instance variable holds the object itself?

Instance variables never hold the objects themselves.
Ruby variables always hold references to objects.

Note: It is often explained that in some special cases
Ruby variables hold 'immediate values'. Such as small
integers as Fixnum instances and the unique objects
nil, false, and true. I think that this is an
unnecessary complication. It is easier and more
consistent to always talk about references. In
particular assignment is always about copying a
reference and *never* about duplicating an object
or a value:

a = 1 # 1 is a reference to a Fixnum
# now a references the same fixnum
b = a # b now references the same fixnum as a

a = "foo" # a is a reference to a string instance
b = a # b now references the same string as a

The 'trick' is to think of literals (-1,0,1,nil,true,false, etc.)
as references and *not* as values or objects.

I'd almost go as far to say that in Ruby there is only
one type of value, an object reference. Assignment, method
argument passing and return values are all about the copying
of references and not at all about objects.

class A; end;

@one = A.new
@two = A.new

p @one.object_id
p @one_object_id
# 21103660
# 21103640

Two different objects, even if they were the same.

Do you have a typo there? Do you want:

p @one.object_id
p @two.object_id

These are two different objects and so they have two
different object ids. I'm not sure what your question
is here.
How does all the nil instance variable reference to the same object?

Can you rephrase the question? I'm not sure what you are asking.

@a = nil
@b = @a
@c = @b

All three instance variables now reference the same object. It
is the same object referenced by the literal, nil. Don't think
of 'nil' as an object. Think of it as a reference to a particular
distinguished object.
 
R

Rick DeNatale

Start a brand new session of IRB and try:

irb> instance_variables
=> []
irb> @alpha
=> nil
irb> instance_variables
=> ["@alpha"]
irb> @beta = 42
=> 42
irb> instance_variables
=> ["@alpha", "@beta"]
irb> instance_variable_set("@gamma", 'foo')
=> "foo"
irb> instance_variables
=> ["@alpha", "@beta", "@gamma"]

Not quite:irb(main):001:0> instance_variables
=> []
irb(main):002:0> @alpha
=> nil
irb(main):003:0> instance_variables
=> []
irb(main):004:0> @beta = 42
=> 42
irb(main):005:0> instance_variables
=> ["@beta"]
irb(main):006:0> defined? @alpha
=> nil
irb(main):007:0> defined? @beta
=> "instance-variable"
Instance variables come into existence when
1) they appear on the left side of an assignment, in which case
they are
initialized to the value on the right hand side of the assignment Yes
2) when they are referenced in an expression, in which case they are
initialized with a reference to the nil object.

No, they are not initialized (or even defined) at this point. They
just evaluate syntactically to nil. See line 6 above.

3) when they are set via a call to instance_variable_set()

Yes.


Note that the result of the defined? operator is a syntactic
description of the argument.

In line 6 above defined? @alpha is not saying that the value of
@alpha is nil, but that since it @alpha isn't defined, there's no
description, and since nil is treated as false in Ruby logical
expressions and anything other than nil and false is treated as true
you can do things like
p @alpha if defined? @alpha

Here's another subtlety:
irb(main):008:0> defined? nil
=> "nil"

Note that it's not returning the value nil, but the descriptive string "nil".

From the ruby 1.8.5 source, the values which defined? can return are
"assignment", "class variable", "constant", "expression",
"global-variable", "instance-variable", "local-variable",
"local-variable(in-block)", "false", "method", "self", "super",
"true", "yield", and nil

It can also return things like "$1", "$2" etc. and "$$", "$`", "$/",
"$'", and "$+" for regexp match references. These are only defined
after a regexp match which sets them, until a regexp match which
doesn't.
 
J

Jamal Soueidan

Gary said:
Do you have a typo there? Do you want:

p @one.object_id
p @two.object_id

I thought that if both @instance don't have the same object_id they
would two different objects...but that is not true?
 
G

Gary Wright

No, they are not initialized (or even defined) at this point. They
just evaluate syntactically to nil. See line 6 above.

Thanks for the correction. I could have sworn that I tested that code
before posting to make sure I understood what was going on. Maybe I
had some left over variables from earlier in the irb session.

So it is *only* assignment and instance_variable_set that will cause
an instance variable to become defined and bound to a reference.

Undefined instance variables evaluate to nil.


Gary Wright
 
G

Gary Wright

I thought that if both @instance don't have the same object_id they
would two different objects...but that is not true?

That is true. All objects have unique object ids. If the objects
referenced by two variables have the same object id then you've got
two references to the same object.

In your original post you had:
@one = A.new
@two = A.new

p @one.object_id
p @one_object_id # TYPO???
# 21103660
# 21103640

Which just doesn't make sense. Specifically, @one_object_id isn't
defined in your example (note the underscore instead of dot)
and should have evaluated to nil. Since you illustrated two
different object_id's, I assumed you had simply made
some sort of cut and paste error and you had intended to show
@two.object_id and not @one_object_id.
 
B

Brian Candler

Now the question is,

When does the instance variable holds the object itself?

Instance variables hold references to what ever object you assigned to them.
class A; end;

@one = A.new
@two = A.new

p @one.object_id
p @one_object_id
# 21103660
# 21103640

Two different objects, even if they were the same.

Perhaps you'd find it helpful if you tried to work out yourself what was
going on - and if you can't, explain your own explanation and why you think
it is wrong.

But to answer it for you:

(1) A.new generates a new instance of class A. Every time you invoke A.new
you get a fresh object. Each object has a unique object_id during its
lifetime.

(2) '@one = A.new' assigns (a reference to) the newly-created object into an
instance variable. Since this assignment is "out in the wild", i.e. not
inside any "class Foo .. end" or "def bar .. end" construct, then you are
assigning to an instance variable of a top-level session object called
'main'

A longer way of writing it would have been:

main.instance_variable_set:)@one, Foo.new)

Then assigning to @two you'll get another object reference stored there.

Clearly then, puts @one.object_id and puts @two.object_id will show you
distinct references to the two distinct objects you created.

Try also:

puts main.inspect
puts main.instance_variables

However unless you're just playing around in irb, nobody creates instance
variables inside 'main'. You normally create them within an object of your
own.

Brian.
 
C

Chad Perrin

Instance variables hold references to what ever object you assigned to them.


Perhaps you'd find it helpful if you tried to work out yourself what was
going on - and if you can't, explain your own explanation and why you think
it is wrong.

But to answer it for you:

(1) A.new generates a new instance of class A. Every time you invoke A.new
you get a fresh object. Each object has a unique object_id during its
lifetime.

(2) '@one = A.new' assigns (a reference to) the newly-created object into an
instance variable. Since this assignment is "out in the wild", i.e. not
inside any "class Foo .. end" or "def bar .. end" construct, then you are
assigning to an instance variable of a top-level session object called
'main'

A longer way of writing it would have been:

main.instance_variable_set:)@one, Foo.new)

Then assigning to @two you'll get another object reference stored there.

Clearly then, puts @one.object_id and puts @two.object_id will show you
distinct references to the two distinct objects you created.

If you want two separate names for the same object with the same object
ID (aka the same object_id), you could chain assignments together:

irb(main):003:0> three = four = A.new
=> #<A:0x80566b4>
irb(main):004:0> three.object_id === four.object_id
=> true
irb(main):005:0> p three.object_id
67285850
=> nil
irb(main):006:0> p four.object_id
67285850
=> 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,787
Messages
2,569,631
Members
45,338
Latest member
41Pearline46

Latest Threads

Top