Forum: Ruby Beginner's tutorial and poor attempt at classes

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Gabriel D. (Guest)
on 2007-08-02 18:12
(Received via mailing list)
Hi all

I just started with Ruby (yesterday actually). Have been reading the
amazing Poignant Guide, and also a couple of other very basic
tutorials. From one of these I wrote an example class, now my
knowledge of Ruby has expanded a little I tried to rewrite the class
to be even better.  I thought that the method "setme" would allow the
@numberShowing to be changed to any number between 1 and 6... but
obviously not...?


#/usr/bin/env ruby

class Die
   def initialize
     roll
   end

   def roll
     @numberShowing = 1 + rand(6)
   end
    def showing
     @numberShowing
   end

   def setme value
        if value === 1..6
       @numberShowing = value
     else
       puts "A dice has only six sides!"
     end
   end

end



Best regards


Gabriel D.

removed_email_address@domain.invalid
unknown (Guest)
on 2007-08-02 18:20
(Received via mailing list)
Hi --

On Thu, 2 Aug 2007, Gabriel D. wrote:

> #/usr/bin/env ruby
>   @numberShowing
> end
You've got the === backwards; you want:

   if (1..6) === value

or

   if (1..6).include?(value)

Here's a little rewrite, using a reader attribute to streamline the
retrieval of the die's number:

class Die
   attr_reader :number

   def initialize
     roll
   end

   def roll
     self.number = rand(6) + 1
   end

   def number=(value)
     if (1..6).include?(value)
       @number = value
     else
       puts "A die has only six sides!"
     end
   end
end

With this, you can do things like:

die = Die.new
puts die.number
die.roll
puts die.number
die.number = 20    # A die has only six sides!

You could also make the number= method private, to discourage (though
not entirely prevent, since private doesn't do that) people from
setting the number manually.


David
Gabriel D. (Guest)
on 2007-08-02 18:34
(Received via mailing list)
On 2 Aug 2007, at 15:18, removed_email_address@domain.invalid wrote:

>> class to be even better.  I thought that the method "setme" would
>>
>>   else
> or
>
>   if (1..6).include?(value)

Thank you very much, these work a treat! I've got to now ask the
inevitable question - why do they work? What difference does it make
which side the things being compared are? I'm sure I'll come across
the answer myself as I continue to get better with Ruby, but I'd be
glad of an explanation sooner :)


>
>   end
> You could also make the number= method private, to discourage (though
> not entirely prevent, since private doesn't do that) people from
> setting the number manually.
>

An interesting rewrite and no-doubt far superior. I still struggling
with trying to identify the differences between self.???, @, and @@.
As far as Python goes I'd say I understand most all of Python's ways
of dealing with classes, these Ruby ones.... are gonna take some
time! Thanks again for your fast and comprehensive reply, it's much
appreciated.

Gabriel D.

removed_email_address@domain.invalid
Stefano C. (Guest)
on 2007-08-02 18:44
(Received via mailing list)
Alle giovedì 2 agosto 2007, Gabriel D. ha scritto:
> Thank you very much, these work a treat! I've got to now ask the  
> inevitable question - why do they work? What difference does it make  
> which side the things being compared are? I'm sure I'll come across  
> the answer myself as I continue to get better with Ruby, but I'd be  
> glad of an explanation sooner :)

When ruby sees an operator, for instance a + b, it calls the
corresponding
method of the first operand, the one on the left, passing the second
operand
as argument. So, a + b becomes:

  a.+(b)

So the line

  value === (1..6)

becomes

  value.===((1..6))

value is an integer, so its === method returns true if the other operand
is a
number with the same value (at least, I think it does, since I haven't
been
able to find any documentation on it). Instead, the line

  (1..6) === value

becomes

  (1..6).===(value)

and the === method of class range returns true if its argument is an
element
of the range itself.

Another situation in which the order of the operands matters, is, for
example,
when multiplying a string and a number:

  'a' * 2  # this means 'a'.*(2)

returns the string 'aa', since the method * of class string returns a
string
containing a number of copies of the receiver. On the other hand,

  2 * 'a'  # this means 2.*('a')

raises an exception, since the method * for a number only performs
number
multiplication.

I hope this helps

Stefano
Drew O. (Guest)
on 2007-08-02 18:52
Gabriel D. wrote:
> I still struggling
> with trying to identify the differences between self.???, @, and @@.

Gabriel -

I'll take a crack at trying to help you with these symbols.

@ - this designates an instance variable within an object. The value of
this variable differs between instances of the same class.

@@ - this is a class variable. The value of this variable is the same
between ALL instances of the same class.

self.* - this is used to declare class methods. You call these methods
directly on a class rather than using a instance of a class.

Below is a little irb session to demonstrate things a bit more:

irb(main):001:0> class Foo
irb(main):002:1>   def initialize
irb(main):003:2>     @inst = 0
irb(main):004:2>     @@cls = 0
irb(main):005:2>   end
irb(main):006:1>   def increment_instance
irb(main):007:2>     @inst += 1
irb(main):008:2>   end
irb(main):009:1>   def increment_class
irb(main):010:2>     @@cls += 1
irb(main):011:2>   end
irb(main):012:1>   def print_stats
irb(main):013:2>     puts "class var: #{@@cls}, instance var: #{@inst}"
irb(main):014:2>   end
irb(main):015:1>   def self.say_hello
irb(main):016:2>     puts "Hello from a class method!"
irb(main):017:2>   end
irb(main):018:1> end
=> nil
irb(main):019:0>
irb(main):020:0* one_foo = Foo.new
=> #<Foo:0x28d0f34 @inst=0>
irb(main):021:0> two_foo = Foo.new
=> #<Foo:0x28ced60 @inst=0>
irb(main):022:0>
irb(main):023:0* 2.times{ one_foo.increment_instance }
=> 2
irb(main):024:0> one_foo.increment_class
=> 1
irb(main):025:0>
irb(main):026:0* one_foo.print_stats
class var: 1, instance var: 2
=> nil
irb(main):027:0>
irb(main):028:0* two_foo.increment_instance
=> 1
irb(main):029:0> two_foo.increment_class
=> 2
irb(main):030:0>
irb(main):031:0* two_foo.print_stats
class var: 2, instance var: 1
=> nil
irb(main):032:0>
irb(main):033:0* Foo.say_hello
Hello from a class method!
=> nil

Welcome to ruby! (it's wayyyy better than python :)
Drew O. (Guest)
on 2007-08-02 18:56
Drew O. wrote:
> Gabriel D. wrote:
>> I still struggling
>> with trying to identify the differences between self.???, @, and @@.
>
> Gabriel -
>
> I'll take a crack at trying to help you with these symbols.

Whoops! I should not be resetting the class variable inside initialize!
It doesn't effect the output of the previous example, though:

class Foo

  @@cls = 0

  def initialize
    @inst = 0
  end
  def increment_instance
    @inst += 1
  end
  def increment_class
    @@cls += 1
  end
  def print_stats
    puts "class var: #{@@cls}, instance var: #{@inst}"
  end
  def self.say_hello
    puts "Hello from a class method!"
  end
end
Gabriel D. (Guest)
on 2007-08-02 19:31
(Received via mailing list)
On 2 Aug 2007, at 15:53, Drew O. wrote:

> this variable differs between instances of the same class.
> irb(main):002:1>   def initialize
> irb(main):013:2>     puts "class var: #{@@cls}, instance var: #
> irb(main):021:0> two_foo = Foo.new
> irb(main):027:0>
> Hello from a class method!
> => nil
>
> Welcome to ruby! (it's wayyyy better than python :)



WOW! What  a reply! This has got to be the single best thing for Ruby
- the peeps on this mailing list are awesome!! Very dry, unwelcoming,
and sometimes rude on the Python list - doesn't apply to everyone on
there, some peeps are dashing, but the majority...

Anyway. That example does make it somewhat clearer, thank you. I
think that all in all I do understand what these things are and what
they do, however, because I haven't come across them before I just
feel a little unsure when to use them, or even when it's best to use
them.

Oh one other thing I am liking more about ruby than python is the
different approaches taken by the languages. I'm starting to have
warm feelings for Ruby because it's more... human. I can write the
code using blocks, on one line, or whatever I deem best for that
particular item. I thought the compulsory white space in Python was
good, but it makes coding very 'rigid'. Well anyway, enough about
this Python vs Ruby thing, I obviously don't need to harp on about it
to the people on this list - you've already settled in the newfoundland!

I'm looking forward to the version of Ruby that gives you a .rbc :)
then things will be even faster!
Ilan B. (Guest)
on 2007-08-03 18:49
Gabriel D. wrote:
> On 2 Aug 2007, at 15:53, Drew O. wrote:
>

>
> Oh one other thing I am liking more about ruby than python is the
> different approaches taken by the languages. I'm starting to have
> warm feelings for Ruby because it's more... human. I can write the
> code using blocks, on one line, or whatever I deem best for that
> particular item. I thought the compulsory white space in Python was
> good, but it makes coding very 'rigid'. Well anyway, enough about
> this Python vs Ruby thing, I obviously don't need to harp on about it
> to the people on this list - you've already settled in the newfoundland!
>
> I'm looking forward to the version of Ruby that gives you a .rbc :)
> then things will be even faster!


Gabriel D.,

Welcome to the board, If I can make one suggestion, it would be to
refrain from direct comparisons to other languages as it invites flames
and trolls and may detract from your experience here on this forum.

Glad you came here however and this forum was one of the primary reasons
I fell in love with the language.  Although it has been suggested that
many in the ruby  upper echelon no longer post here, I have noticed that
many amazing developers have stepped up and have taken their place, so
of course I leech off of them every chance I get!  :)

ilan
Robert K. (Guest)
on 2007-08-03 19:08
(Received via mailing list)
2007/8/2, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid>:
>    def number=(value)
>      if (1..6).include?(value)
>        @number = value
>      else
>        puts "A die has only six sides!"
>      end
>    end
> end

Interesting that you do it that way.  In the light of exception
handling, I would rather have done

def number=(v)
  raise ArgumentError, "not a valid dice value: #{v}" unless
(1..6).include? v
  @number = v
end

Apparently everybody has different approaches. :-)

Kind regards

robert
Gabriel D. (Guest)
on 2007-08-03 22:08
(Received via mailing list)
On 2 Aug 2007, at 15:18, removed_email_address@domain.invalid wrote:

>> class to be even better.  I thought that the method "setme" would
>>
>>   else
> or
>     roll
>   end
>
>   def roll
>     self.number = rand(6) + 1
>   end


Have been rereading your example. Just wanted to ask why in the code
just above did you use  "self.number"  which you changed from @number?


>
>   def number=(value)
>     if (1..6).include?(value)
>       @number = value
>     else
>       puts "A die has only six sides!"
>     end
>   end
> end

and then here "@number" is used.. finding this a little confusing.
Thanks again, for all your help.
Gabriel D. (Guest)
on 2007-08-03 22:10
(Received via mailing list)
On 3 Aug 2007, at 15:49, Ilan B. wrote:

>> good, but it makes coding very 'rigid'. Well anyway, enough about
> Welcome to the board, If I can make one suggestion, it would be to
> of course I leech off of them every chance I get!  :)
>
> ilan
>
>

Thank you for your suggestion, Ilan, I'll certainly be more careful
in the future. I hope that I can learn a lot and have a good
experience from this community, and later start to give back and help
others when I'm more knowledgeable.

Regards

Gabriel
unknown (Guest)
on 2007-08-03 22:22
(Received via mailing list)
Hi --

On Sat, 4 Aug 2007, Gabriel D. wrote:

>>> amazing Poignant Guide, and also a couple of other very basic tutorials.
>>>  roll
>>>     if value === 1..6
>>  if (1..6) === value
>>
> above did you use  "self.number"  which you changed from @number?
>> end
>
> and then here "@number" is used.. finding this a little confusing. Thanks
> again, for all your help.

The number= method does some data checking, and if all is well it sets
@number.  I don't want to set @number directly, because the checking
won't happen.  I guess rand(6) + 1 is pretty safe, but still, since my
setter method does more than just set @number, it's "polite" to go
through that method instead of just setting @number.


David
Gabriel D. (Guest)
on 2007-08-04 00:57
(Received via mailing list)
On 3 Aug 2007, at 19:21, removed_email_address@domain.invalid wrote:
[...SNIP...]


>>
>> and then here "@number" is used.. finding this a little confusing.
>> Thanks again, for all your help.
>
> The number= method does some data checking, and if all is well it sets
> @number.  I don't want to set @number directly, because the checking
> won't happen.  I guess rand(6) + 1 is pretty safe, but still, since my
> setter method does more than just set @number, it's "polite" to go
> through that method instead of just setting @number.


Hi David

Thank you for your quick reply and help. I have to confess I'm being
quite dumb about this, I still don't understand 100% why one should
use self.number.... but I think that's something that I need to work
on and all will become clear as I become more familiar with Ruby as a
whole. I've bought on Amazon a book called Beginning Ruby, dunno if
it's any good, but I should received it tomorrow (fingers crossed!)
so I can study it over the weekend.

My full time job is a web programmer, I've got a couple of large
projects coming up, and because my boss is cool I can use any
language/framework I like. Naturally I've chosen Rails.... I hope to
get my Ruby up to speed for this, and I'll be needing a good RoR
book. I see that you yourself have authored some books. That's
awesome! Do you think your rails books would fit my needs? Also, is
there anywhere I can view several pages from it?


Best regards


Gabriel D.

removed_email_address@domain.invalid
unknown (Guest)
on 2007-08-04 01:29
(Received via mailing list)
Hi --

On Sat, 4 Aug 2007, Gabriel D. wrote:

>>>
>>>>   end
>> through that method instead of just setting @number.
>
>
> Hi David
>
> Thank you for your quick reply and help. I have to confess I'm being quite
> dumb about this, I still don't understand 100% why one should use
> self.number.... but I think that's something that I need to work on and all
> will become clear as I become more familiar with Ruby as a whole. I've bought
> on Amazon a book called Beginning Ruby, dunno if it's any good, but I should
> received it tomorrow (fingers crossed!) so I can study it over the weekend.

It's really just so the data filtering and checking will happen.
Here's another example -- a Person class where every new Person object
gets a name, and the name is stored in uppercase:

   class Person
     attr_reader :name

     def initialize(name)
       self.name = name.chomp
     end

     def name=(name)
       @name = name.upcase
     end
   end

   print "Name: "
   name = gets
   p = Person.new(name)

   puts "Your name has been recorded as #{p.name}."

I could write initialize like this:

   @name = name.chomp

But then I'd be bypassing the upcasing of the name.  So by calling the
method, even from within other methods in the class, I'm respecting
the filtering that I've put in place.

Meanwhile, attr_reader :name gives me an automatic "reader" method.
Unlike the writer method (name=) I'm using the default, which will
just return the current value of the instance variable @name.

> My full time job is a web programmer, I've got a couple of large projects
> coming up, and because my boss is cool I can use any language/framework I
> like. Naturally I've chosen Rails.... I hope to get my Ruby up to speed for
> this, and I'll be needing a good RoR book. I see that you yourself have
> authored some books. That's awesome! Do you think your rails books would fit
> my needs? Also, is there anywhere I can view several pages from it?

At http://www.manning.com/black there are some sample chapters.  I
think you'd get a lot out of the book, but I'll abstain and let the
chapters speak for themselves :-)


David
Gabriel D. (Guest)
on 2007-08-04 20:39
(Received via mailing list)
On 2 Aug 2007, at 15:18, removed_email_address@domain.invalid wrote:

>> class to be even better.  I thought that the method "setme" would
>>
>>   else
> or
>
>   if (1..6).include?(value)


and I just discovered yet another way of getting to the same place!!
     if value.between?(1, 6)

IMO the prettiest code to read, but which one *should* be used, or is
it all OK so long as it works?

Regards

Gabe
Pit C. (Guest)
on 2007-08-06 22:30
(Received via mailing list)
2007/8/4, Gabriel D. <removed_email_address@domain.invalid>:
> and I just discovered yet another way of getting to the same place!!
>      if value.between?(1, 6)
>
> IMO the prettiest code to read, but which one *should* be used, or is
> it all OK so long as it works?

Gabe, your version should be more efficient, because it doesn't create
a new Range object. So  go for it!

Regards,
Pit
This topic is locked and can not be replied to.