Some newbie questions - bare with me ;)

E

egervari

Question 1
I was curious what ":" before a identifier was exactly. It seems that
it's often used as a map key... but what is it exactly?

Printing :bob to the screen results in "bob"... but testing for
equality between :bob and "bob" results in a falsehood.

I figure this has to be some literal notation for something, but what?

Question 2
In RSpec, it uses == for equality. I overrode the eql?() method in
object, but == doesn't use it. I am used to languages providing an
equals() method that you can override. So if you want 1:1 equals, you
must use eql? and == is just comparing the object id's? So does that
mean that the literal 1 uses the same object no matter where that
literal is used?

It just seems a little weird to me that if everything is an object...
then my assumption would be that == would compare the actual state and
not the object references like it does in Java. Can you clear this up?
Thanks!

Question 3
Ruby seems to @ in front of an identifier to denote that it's an
instance variable. I'm curious, what is the reason for this? And if
these variables are in fact private to the object, is there some kind
of short-hand to create getter/setters?, or do you have to define
these 2 def's yourself? I guess if that's the case, it's no worse than
in Java, but Scala provides several ways to get around this. I'm
curious if such shorthands exist.

Thanks!
 
J

Jesús Gabriel y Galán

Question 1
I was curious what ":" before a identifier was exactly. It seems that
it's often used as a map key... but what is it exactly?

Printing :bob to the screen results in "bob"... but testing for
equality between :bob and "bob" results in a falsehood.

I figure this has to be some literal notation for something, but what?

It's a Symbol.

http://ruby-doc.org/core/classes/Symbol.html

A Symbol is an object of which there only exists one. Every time you
use the literal :bob, it's the same object. They are usually used as
Hash keys, as flags, and so on.
Question 2
In RSpec, it uses == for equality. I overrode the eql?() method in
object, but == doesn't use it. I am used to languages providing an
equals() method that you can override. So if you want 1:1 equals, you
must use eql? and == is just comparing the object id's? So does that
mean that the literal 1 uses the same object no matter where that
literal is used?

It just seems a little weird to me that if everything is an object...
then my assumption would be that == would compare the actual state and
not the object references like it does in Java. Can you clear this up?
Thanks!

Check this:
http://ruby-doc.org/core/classes/Object.html

methods ==, eql? and equals?

Also this:

http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html

There's a very good explanation about the equivalence concepts and
best practices in Ruby.
Question 3
Ruby seems to @ in front of an identifier to denote that it's an
instance variable. I'm curious, what is the reason for this? And if
these variables are in fact private to the object, is there some kind
of short-hand to create getter/setters?, or do you have to define
these 2 def's yourself? I guess if that's the case, it's no worse than
in Java, but Scala provides several ways to get around this. I'm
curious if such shorthands exist.

attr_accessor :a # creates methods a= and a
attr_reader # creates method a
attr_writer # creates method a=

Jesus.
 
E

egervari

Ah, thanks for all of those answers. It helps very much. I didn't know
I could override == instead of eql?, and this fixed the problem with
RSpec ;) Makes much more sense, and I'd rather use == than equals, or
eql. I'm glad that it's not just a bad design decision carried over
from Java that even Java should not have had in it's original design.

The symbol object makes sense. I guess one thing that is hard to
understand is that Ruby seems to keep a flyweight for some classes,
but not others. I'm guessing numbers, symbols and others have this
automatic flyweight thing going on. I suppose I can just use == for
them, and then override == in my personal classes to make them behave
the same way.

Thanks again for all the info.
 
S

Stefano Crocco

|Question 1
|I was curious what ":" before a identifier was exactly. It seems that
|it's often used as a map key... but what is it exactly?
|
|Printing :bob to the screen results in "bob"... but testing for
|equality between :bob and "bob" results in a falsehood.
|
|I figure this has to be some literal notation for something, but what?

It is a Symbol. Symbols are sequences of characters with the property that
each sequence has a unique identity. This means that the symbol :abc will be
represented by the same object everywhere I use it. For example, in the
following code:

x = :abc
y = :abc

x and y contain the same object. This is unlike what happens with strings,
where each string literal produces a new object:

x = 'abc'
y = 'abc'

x and y contain two strings with the same contents but different identity (as
you can see by using the object_id method).

Because of their properties, symbols are often used instead of strings when
you're not interested in the content of the string, but are only using it as a
unique identifier. This is what happens in hashes.

As for the equality test, a string is not a symbol, so 'bob'==:bob fails.

You can learn more about the difference between strings and symbols searching
this mailing list for things like "difference between string and symbol".
|Question 2
|In RSpec, it uses == for equality. I overrode the eql?() method in
|object, but == doesn't use it. I am used to languages providing an
|equals() method that you can override. So if you want 1:1 equals, you
|must use eql? and == is just comparing the object id's? So does that
|mean that the literal 1 uses the same object no matter where that
|literal is used?
|
|It just seems a little weird to me that if everything is an object...
|then my assumption would be that == would compare the actual state and
|not the object references like it does in Java. Can you clear this up?
|Thanks!

Ruby provides three methods to compare objects:
* equal? this method compares the identity of objects. That is, obj1.equal?
(obj2) is true if and only if their object_id is the same. This method is
defined in Object and shouldn't (usually) be overridden
* == this method is used for comparing tow objects basing on their contents.
For class Object, this is the same as equal? (comparing object identity), but
other classes may override it to give results basing on the objects' contents.
For example, Array overrides this method to return true if the two arrays have
the same size and their contents are the same (according to the == method of
each object)
* eql? this is a method used by hashes to check for the equality of keys. It
usually have the same meaning as ==, but some class change it. You usually
don't need to change this

Your problem comes from the fact that you overrode the eql? method rather than
the == method
|Question 3
|Ruby seems to @ in front of an identifier to denote that it's an
|instance variable. I'm curious, what is the reason for this? And if
|these variables are in fact private to the object, is there some kind
|of short-hand to create getter/setters?, or do you have to define
|these 2 def's yourself? I guess if that's the case, it's no worse than
|in Java, but Scala provides several ways to get around this. I'm
|curious if such shorthands exist.

Use the attr_reader, attr_writer and attr_accessor class methods. Attr reader
defines a getter method named as the instance variable, attr_writer defines a
setter method named as the instance variable followed by an = and
attr_accessor does both. For example:

class C

attr_reader :x
attr_writer :y
attr_accessor :z

end

is the same as

class C

def x
@x
end

def y= value
@y = value
end

def z
@z
end

def z= value
@z = value
end
end

I hope this helps

Stefano
 
R

Robert Klemme

Ah, thanks for all of those answers. It helps very much. I didn't know
I could override == instead of eql?, and this fixed the problem with
RSpec ;) Makes much more sense, and I'd rather use == than equals, or
eql. I'm glad that it's not just a bad design decision carried over
from Java that even Java should not have had in it's original design.

But please note that #== in Ruby is not the same as == in Java.
Ruby's #equal? compares for object identity (in Java ==). Methods #==
and #eql? are (most of the time) just two ways to access the same
underlying logic. If you implement #== you should also implement
#eql? because the latter method is used by Hash and Set (see my blog
article that Jesus referred you to).

Kind regards

robert
 

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,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top