Some newbie questions

I got some newbie questions which I would very much appreciate if
someone could answer (in a way that a newbie would understand):

  1. What does @ mean in Ruby? Im sure I have seen variables like this:
    @variable. A new datatype like the :symbol perhaps?

  2. myhash = Hash.new {0}
    anotherhash.values.each {|x| thecreatedhash[x] += 1}

What makes the hash created above different from a hash created the
normal way? I can execute the block on a hash created with that method
but not a normal empty hash created manually.

  1. Is there any difference between these three:

Dir.entries “the directory”
Dir[""]
Dir.glob "
"

If you use them on the same directory?

Thanks in advance!

Vladimir Van B. wrote in post #1022210:

I got some newbie questions which I would very much appreciate if
someone could answer (in a way that a newbie would understand):

  1. What does @ mean in Ruby? Im sure I have seen variables like this:
    @variable. A new datatype like the :symbol perhaps?

The @ means that the variable is an object variable, its scope is
within, and is associated to, the current object.

For example,

class Person
def initialize(name)
@name=name
end

def say_your_name
puts @name
end

In this class, you assign the name provided to the class to @name.
@name as an object variable, is then accessible from any other method
inside the object.

On Fri, Sep 16, 2011 at 04:46:28AM +0900, Vladimir Van B.
wrote:

  1. Hash.new {0}
    anotherhash.values.each {|x| thecreatedhash[x] += 1}

What makes the hash created above different from a hash created the
normal way? I can execute the block on a hash created with that method
but not a normal empty hash created manually.

What exactly do you mean by “the normal way”?

alberto kaputchella:

The @ means that the variable is an object variable, its scope is
within, and is associated to, the current object.

For example,

class Person
def initialize(name)
@name=name
end

def say_your_name
puts @name
end

In this class, you assign the name provided to the class to @name.
@name as an object variable, is then accessible from any other method
inside the object.

So the @-sign in Ruby is like self in Python? Can someone confirm who
knows Python?

Chad P.:

What exactly do you mean by “the normal way”?

I meant like this: myhash = {}, sorry for being unclear.

On Thu, Sep 15, 2011 at 10:57 PM, Vladimir Van B.
[email protected] wrote:

end

def say_your_name
puts @name
end

In this class, you assign the name provided to the class to @name.

Not to the class - to the instance! Or more precisely the name is
passed to Person#new which forwards it to #initialize after allocating
the instance.

@name as an object variable, is then accessible from any other method
inside the object.

So the @-sign in Ruby is like self in Python? Can someone confirm who
knows Python?

I do not know Python but I assume “self” in Python is the same as
“self” in Ruby: a reference to the current object.

Variable names prefixed with @ really set the scope of the variable to
be the instance and not the current method. “@foo” is an instance
variable of whatever self is at the moment and “foo” is a local
variable. I suggest you play around with these a bit - I am sure you
will quickly notice the difference.

Chad P.:

What exactly do you mean by “the normal way”?

I meant like this: myhash = {}, sorry for being unclear.

myhash = {} is the same as myhash = Hash.new - only less typing.

Kind regards

robert

On Sep 15, 2011, at 3:46 PM, Vladimir Van B. wrote:

  1. Hash.new {0}
    anotherhash.values.each {|x| thecreatedhash[x] += 1}

What makes the hash created above different from a hash created the
normal way? I can execute the block on a hash created with that method
but not a normal empty hash created manually.

A hash created via a literal:

hash1 = {}

has a default value of nil:

hash1[‘foo’] # returns nil

A hash created as you suggested:

hash2 = Hash.new { 0 }

computes a value whenever the key lookup fails. In this case the
computation
is the trivial expression: 0 but it could be something arbitrarily
complicated
and can depend on the key itself

hash3 = Hash.new { |hash, key| hash[key] = key.reverse }
hash3[‘hello’] # returns ‘olleh’

If you want the returned value to be saved for future lookups with the
same key,
then you have to store the value in the hash explicitly as shown above.
Otherwise
a new value will be recomputed for each key lookup (even for multiple
lookups of
the same key).

If you just want a hash that defaults to 0 for missing keys then you
don’t really
need the block form where you ‘compute’ zero each time. Use this form
instead:

hash4 = Hash.new(0)
hash4[42] # returns 0

Be careful with this form though because it is the exact same object
that is
returned for the value of all missing keys:

hash5 = Hash.new([]) # an array is allocated here and used for all
missing keys
apple = hash5[‘apple’] # the array allocated and passed to Hash.new
banana = hash5[banana’] # the same array!

apple.equal?(banana) # true

In this case, you almost always want to allocate a brand new array for
each
key miss. Time to go back to the block format:

hash6 = Hash.new {|h,k| h[k] = [] } # allocate a brand new array for
each key miss

Gary W.

On Thu, Sep 15, 2011 at 15:46, Vladimir Van B.
[email protected] wrote:

  1. What does @ mean in Ruby? Im sure I have seen variables like this:
    @variable. A new datatype like the :symbol perhaps?

Someone beat me to this one, so I’ll just preemptively add, @@ means
it’s a class variable.

  1. Hash.new {0}
    anotherhash.values.each {|x| thecreatedhash[x] += 1}

What makes the hash created above different from a hash created the
normal way? I can execute the block on a hash created with that method
but not a normal empty hash created manually.

You’ve already clarified that “normal” means {}. But what I don’t get
is how you’re using it. Do you mean that:

thecreatedhash = Hash.new {0}
anotherhash.values.each {|x| thecreatedhash[x] += 1}

yields different results from:

thecreatedhash = {}
anotherhash.values.each {|x| thecreatedhash[x] += 1}

? That boils down to the difference between “Hash.new {0}” and “{}”.
The latter will return an empty hash such that uninitialized slots
have a nil value, as usual. The former is a good bit more
complicated. There is documentation at:

http://www.ruby-doc.org/core/classes/Hash.html#M000718

At first glance the docs would lead me to believe that the
uninitialized slots should return the value {0}, using the
Hash.new(object) syntax, but the braces in fact make it take that as a
code block, even though it’s not using the args, so it’s using the
third syntax (Hash.new {|hash, key| block }). This means it returns
0, the result of that code block, for all uninitialized slots.
Occasional confusion between hashes and code blocks is one of the
subtleties of Ruby.

So, in the former case, anotherhash would cause corresponding slots of
thecreatedhash to be set to 1, because they start at 0 and get
incremented. In the latter, they’d start as nil, and you can’t add 1
to that, so you’d get a NoMethodError. Is ths the behavior you’re
seeing?

-Dave

So the @-sign in Ruby is like self in Python? Can someone confirm who
knows Python?

Not so much. Much like Python, Ruby classes deal with self as well.
However in Ruby that’s passed around behind the scenes, so you won’t see
it in method definitions. Take for example the following:


class Test:
… myvar = “This is a variable”
… def mymethod(self):
… return self.myvar

inst = Test()
inst.mymethod()
‘This is a variable’


Here in this case, the instance of Test, inst is being passed in as
“self” to mymethod. Now something to note is that here:


myvar = “This is a variable”

Has the same self as


return self.myvar

Now in Ruby, things are different. When defining classes, self inside
the class definition can be referring to two different things. Take for
example a copy of the above:


irb(main):001:0> class Test
irb(main):002:1> @myvar = “This is a variable”
irb(main):003:1> def mymethod
irb(main):004:2> @myvar
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> inst = Test.new
=> #Test:0x0000010202eb00
irb(main):008:0> inst.mymethod
=> nil
irb(main):009:0>

Noticed that mymethod returned nil. This is because self in the
context of where @myvar is located is the CLASS ITSELF:


irb(main):009:0> class Test
irb(main):010:1> p self
irb(main):011:1> @myvar = “This is a variable”
irb(main):012:1> def mymethod
irb(main):013:2> @myvar
irb(main):014:2> end
irb(main):015:1> end
Test
=> nil

That is because class definitions in Ruby are expressions that evaluate
to the last statement of the class definition. In this case method
definitions return nil, so that’s the resulting value. We could change
this however:


irb(main):018:0> class Test
irb(main):019:1> @myvar = “This is a variable”
irb(main):020:1> def mymethod
irb(main):021:2> @myvar
irb(main):022:2> end
irb(main):023:1> “return value”
irb(main):024:1> end
=> “return value”

  1. Is there any difference using Dir.entries “the directory”
    compared to using
    Dir.glob “*” if you use them on the same directory?

Yes. Dir.glob ‘*’ will not return Unix-style hidden files (files that
start with a dot).

Example:
sampledir
|-- .
|-- …
|-- foo.txt
|-- .bar.txt

Dir.glob("*") #=> [‘foo.txt’] #if Dir.pwd = sampledir
Dir.entries(‘sampledir’) #=> [’.’, ‘…’, ‘foo.txt’, ‘.bar.txt’]

On Sep 16, 2011, at 12:49 AM, Gunther D. wrote:

  1. Is there any difference using Dir.entries “the directory”
    compared to using
    Dir.glob “*” if you use them on the same directory?

Yes. Dir.glob ‘*’ will not return Unix-style hidden files (files that
start with a dot).

Unless you ask it to:

irb(main):001:0> Dir[’*’]
=> [“Applications”, “Code”, “cookies.txt”, “Desktop”, “Documents”,
“Downloads”, “git.tar.gz”, “Library”, “Movies”, “Music”, “Pictures”,
“Public”, “Sites”, “tmp”, “Zeraw”]

irb(main):002:0> Dir[’.*’]
=> [".", “…”, “.adobe”, “.autotest”, “.bash_history”, “.bundler”,
“.CFUserTextEncoding”, “.config”, “.cups”, “.DS_Store”, “.dvdcss”,
“.editrocket”, “.fontconfig”, “.gdb_history”, “.gem”, “.gitconfig”,
“.gitk”, “.gnome2”, “.inkscape-etc”, “.irb-history”, “.irb_history”,
“.lesshst”, “.MacOSX”, “.monk”, “.profile”, “.psql_history”,
“.recently-used.xbel”, “.ri”, “.rs”, “.rvm”, “.rvmrc”,
“.sqlite_history”, “.ssh”, “.subversion”, “.Trash”, “.viminfo”,
“.Xauthority”, “.Xcode”]

On Fri, Sep 16, 2011 at 05:57:36AM +0900, Vladimir Van B.
wrote:

Chad P.:

What exactly do you mean by “the normal way”?

I meant like this: myhash = {}, sorry for being unclear.

There have already been some good answers to this, but I’ll throw in
another formulation of the explanation:

myhash = {:foo => 'foo'}
mystring = 'foo'

This assigns a hash literal to myhash and a string literal to mystring.

myhash = {}
mystring = ''

This assigns an empty hash literal to myhash, and an empty string
literal to mystring. In the case of the hash, all attempts to access
hash keys return a value of nil.

myhash = Hash.new
mystring = String.new

This assigns an empty hash to myhash and an empty string to mystring
much
as in the immediately previous case, but does so by explicitly using the
new constructor rather than explicit assignment of a hash literal and
string literal to their respective variable names.

myhash = Hash.new(0)
mystring = String.new('zero')

This assigns a hash to myhash whose default value for nonexistent
strings
is 0, and a string to mystring whose value is ‘zero’.

myhash = Hash.new {|h,k| k.to_s }
mystring = String.new { 'foo' }

This is where they diverge. You can pass a block to Hash.new telling it
what default values should be used for as-yet undefined keys. In this
case, with the hash (as h) and the key (as k) passed to the block as
parameters, myhash[:foo] will return ‘foo’. In the case of this
construction for mystring, the block is thrown away, and you still get
an
empty string.

Thanks for all the helpful answers.

Regarding the first question about @-variables: if I understood it
correctly it simply makes it so that the variable can be used anywhere
within the class and is not limited by variable scopes as long as it is
used within the class. Correct?

Also, do anyone have a good tutorial for learning classes in Ruby? It’s
a little different from classes in Python which I am used to.

2011/9/16 Vladimir Van B. [email protected]:

Regarding the first question about @-variables: if I understood it
correctly it simply makes it so that the variable can be used anywhere
within the class and is not limited by variable scopes as long as it is
used within the class. Correct?

Yes.

– Matma R.