Basic question about Fixnum & Integer

Hello,
I'm really new to Ruby and rather new to OOP in general. I've been using Perl for about 7 years now and have a fairly good understanding of that language. I've never really entertained Python to any serious degree beyond 'Hello World'. Now you know my background.

I tried to do the following:

13.lcd 3

and it failed in the irb.

Why?

My thinking is that 13 is a Fixnum class and Fixnum inherits Integer.
Integer has a method 'lcd' that returns the least common denominator.
Since Fixnum < Integer then all the methods of Integer should be available to all the child objects (Fixnum and super). And if this is true, then calling a method like I did (Fixnum#lcd) implies an inheritance search to find that class.

But my thinking seems to not reflect Ruby very well.

Can someone please tell me what I did wrong in the code and also in thought? It's little niggly bits like this that get frustrating.

Tom Allison wrote:

Hello,
I'm really new to Ruby and rather new to OOP in general. I've been using Perl for about 7 years now and have a fairly good understanding of that language. I've never really entertained Python to any serious degree beyond 'Hello World'. Now you know my background.

I tried to do the following:

13.lcd 3

and it failed in the irb.

Why?

My thinking is that 13 is a Fixnum class and Fixnum inherits Integer.
Integer has a method 'lcd' that returns the least common denominator.
Since Fixnum < Integer then all the methods of Integer should be available to all the child objects (Fixnum and super). And if this is true, then calling a method like I did (Fixnum#lcd) implies an inheritance search to find that class.

But my thinking seems to not reflect Ruby very well.

Can someone please tell me what I did wrong in the code and also in thought? It's little niggly bits like this that get frustrating.

Hi Tom,

There is no method named "lcd" on Integer, unless perhaps you're using an outside library which gives you this functionality.

irb(main):016:0> 5.respond_to? :lcd
=> false

To check what methods an Integer does have you can use the public_methods method on any number.

irb(main):017:0> 5.public_methods.sort
=> ["%", "&", "*", "**", "+", "+@", "-", "-@", "/", "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", "", "^", "__id__", "__send__", "abs", "between?", "ceil", "chr", "class", "clone", "coerce", "display", "div", "divmod", "downto", "dup", "eql?", "equal?", "extend", "floor", "freeze", "frozen?", "hash", "id", "id2name", "inspect", "instance_eval", "instance_of?", "instance_variable_get", "instance_variable_set", "instance_variables", "integer?", "is_a?", "kind_of?", "method", "methods", "modulo", "next", "nil?", "nonzero?", "object_id", "prec", "prec_f", "prec_i", "private_methods", "protected_methods", "public_methods", "quo", "remainder", "respond_to?", "round", "send", "singleton_method_added", "singleton_methods", "size", "step", "succ", "taint", "tainted?", "times", "to_a", "to_f", "to_i", "to_int", "to_s", "to_sym", "truncate", "type", "untaint", "upto", "zero?", "|", "~"]

You can also check ruby-doc for method documentation online, http://www.ruby-doc.org/

Zach

zdennis wrote:

Tom Allison wrote:

Hello,
I'm really new to Ruby and rather new to OOP in general. I've been using Perl for about 7 years now and have a fairly good understanding of that language. I've never really entertained Python to any serious degree beyond 'Hello World'. Now you know my background.

I tried to do the following:

13.lcd 3

and it failed in the irb.

Why?

My thinking is that 13 is a Fixnum class and Fixnum inherits Integer.
Integer has a method 'lcd' that returns the least common denominator.
Since Fixnum < Integer then all the methods of Integer should be available to all the child objects (Fixnum and super). And if this is true, then calling a method like I did (Fixnum#lcd) implies an inheritance search to find that class.

But my thinking seems to not reflect Ruby very well.

Can someone please tell me what I did wrong in the code and also in thought? It's little niggly bits like this that get frustrating.

Hi Tom,

There is no method named "lcd" on Integer, unless perhaps you're using an outside library which gives you this functionality.

irb(main):016:0> 5.respond_to? :lcd
=> false

Yeah... I just caught that.
lcm

shoud I require integer then?

No, you don't have to require integer, because it is in the core. The
core is always available. You can read the docs here:

http://www.ruby-doc.org/core/

And there is a standard library too:

http://www.ruby-doc.org/stdlib/

Most of these are not available by default. If you want to use a YAML
parser, you have to require YAML.

···

--
Posted via http://www.ruby-forum.com/.

Jules wrote:

No, you don't have to require integer, because it is in the core. The core is always available. You can read the docs here:

RDoc Documentation

And there is a standard library too:

RDoc Documentation

Most of these are not available by default. If you want to use a YAML parser, you have to require YAML.

Thanks for the references.

For some reason I can't get my installation of Ruby to do what the examples show:

6.lcm 7

return

>> 6.lcm 7
NoMethodError: undefined method `lcm' for 6:Fixnum
         from (irb):17
>> 6.lcm(7)
NoMethodError: undefined method `lcm' for 6:Fixnum
         from (irb):18

This is too simple to get wrong?

···

from :0
         from :0

You must require 'mathn'

example:

require 'mathn'

6.lcm(7) # -> 42

- Daniel

···

On Jan 16, 2006, at 3:50 PM, Tom Allison wrote:

This is too simple to get wrong?

I had never seen the #lcm method before, but I see it on ruby-doc, and I see it in my local ri, and it also doesn't really exist for me. Very odd. Looks like for some reason the documentation is wrong.

Slim:~ gavinkistner$ irb --version
irb 0.9.5(05/04/13)
Slim:~ gavinkistner$ irb
irb(main):001:0> VERSION
=> "1.8.4"
irb(main):002:0> 6.respond_to? :lcm
=> false
irb(main):003:0> 6.methods.sort
=> ["%", "&", "*", "**", "+", "+@", "-", "-@", "/", "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", "", "^", "__id__", "__send__", "abs", "between?", "ceil", "chr", "class", "clone", "coerce", "display", "div", "divmod", "downto", "dup", "eql?", "equal?", "extend", "floor", "freeze", "frozen?", "hash", "id", "id2name", "inspect", "instance_eval", "instance_of?", "instance_variable_get", "instance_variable_set", "instance_variables", "integer?", "is_a?", "kind_of?", "method", "methods", "modulo", "next", "nil?", "nonzero?", "object_id", "prec", "prec_f", "prec_i", "private_methods", "protected_methods", "public_methods", "quo", "remainder", "respond_to?", "round", "send", "singleton_method_added", "singleton_methods", "size", "step", "succ", "taint", "tainted?", "times", "to_a", "to_f", "to_i", "to_int", "to_s", "to_sym", "truncate", "type", "untaint", "upto", "zero?", "|", "~"]
irb(main):004:0> quit
Slim:~ gavinkistner$ ri lcm
------------------------------------------------------------ Integer#lcm
      lcm(other)

···

On Jan 16, 2006, at 7:50 AM, Tom Allison wrote:

For some reason I can't get my installation of Ruby to do what the examples show:
>> 6.lcm 7
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):17
        from :0
>> 6.lcm(7)
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):18
        from :0

This is too simple to get wrong?

------------------------------------------------------------------------
      Returns the lowest common multiple (LCM) of the two arguments
      (self and other).

      Examples:

        6.lcm 7 # -> 42
        6.lcm 9 # -> 18

Is it true that RubyGems requires mathn? It seems so to me:

gus@guslaptop ~]ruby -e 'p(5.lcm(3))'
-e:1: undefined method `lcm' for 5:Fixnum (NoMethodError)
gus@guslaptop ~]ruby -rubygems -e 'p(5.lcm(3))'
15
gus@guslaptop ~]ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]
gus@guslaptop ~]gem -v
0.8.11

That gives me somewhat of an uneasy feeling. How many core tampering libraries does RubyGems requires that may make me rely on methods which are not really in the core?

Guillaume.

Tom Allison wrote:

···

Jules wrote:

No, you don't have to require integer, because it is in the core. The core is always available. You can read the docs here:

http://www.ruby-doc.org/core/

And there is a standard library too:

RDoc Documentation

Most of these are not available by default. If you want to use a YAML parser, you have to require YAML.

Thanks for the references.

For some reason I can't get my installation of Ruby to do what the examples show:

6.lcm 7

return

>> 6.lcm 7
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):17
        from :0
>> 6.lcm(7)
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):18
        from :0

This is too simple to get wrong?

Actually, this is partially wrong. #lcm is defined in rational, but mathn requires rational. So require 'rational', but require 'mathn' works too. Sorry.

- Daniel

···

On Jan 16, 2006, at 4:01 PM, Daniel Harple wrote:

You must require 'mathn'

Daniel Harple wrote:

This is too simple to get wrong?

You must require 'mathn'

example:

require 'mathn'

6.lcm(7) # -> 42

- Daniel

Thank you. This is the first I've heard of mathn, even from the Integer doc pages. I missed it.

Backing up....

I was assuming that to include a module I would call the class name on the assumption that the class name matches the class file (similar to perl and java). But this isn't the case with mathn.

Doing some more poking about:
ri has nothing known about mathn or anything like it.
ri tells me that Integer.lcm is a real method.
but to invoke this method on a Fixnum, I have to require a package name that isn't mentioned in the lcm, Fixnu, or Integer docs.

Granted, I found all this from the web pages for the standard library, but it wasn't intuitive. It doesn't even mention that mathn is responsible for this lcm method.

This is really frustrating. Is the documentation wrong or did I just miss something that every Ruby-ite should know?

···

On Jan 16, 2006, at 3:50 PM, Tom Allison wrote:

Gavin Kistner wrote:

···

On Jan 16, 2006, at 7:50 AM, Tom Allison wrote:

For some reason I can't get my installation of Ruby to do what the examples show:
>> 6.lcm 7
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):17
        from :0
>> 6.lcm(7)
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):18
        from :0

This is too simple to get wrong?

I had never seen the #lcm method before, but I see it on ruby-doc, and I see it in my local ri, and it also doesn't really exist for me. Very odd. Looks like for some reason the documentation is wrong.

Oh thank God!!! I thought I was going clearly insane.
If I am, at least I won't be alone...

It doesn't require mathn, it requires rational.rb

irb(main):013:0> 1/2
=> 0
irb(main):014:0> require 'rubygems'
=> true
irb(main):015:0> 1/2
=> 0
irb(main):016:0> exit

logan:/Users/logan% ruby -e 'p(5.lcm(3))'
-e:1: undefined method `lcm' for 5:Fixnum (NoMethodError)
logan:/Users/logan% ruby -rubygems -e 'p(5.lcm(3))'
15
logan:/Users/logan% ruby -v
ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0]
logan:/Users/logan% gem -v
0.8.10

irb(main):001:0> old_features = $LOADED_FEATURES.dup
=> ["irb.rb", "e2mmap.rb", "irb/init.rb", "irb/context.rb", "irb/workspace.rb", "irb/extend-command.rb", "irb/ruby-lex.rb", "irb/slex.rb", "irb/ruby-token.rb", "irb/input-method.rb", "readline.bundle", "irb/locale.rb", "tempfile.rb", "delegate.rb", "tmpdir.rb", "irb/completion.rb"]
irb(main):002:0> require 'ubygems'
=> true
irb(main):003:0> new_features = $LOADED_FEATURES - old_features
=> ["ubygems.rb", "rubygems.rb", "rbconfig.rb", "rubygems/rubygems_version.rb", "rubygems/source_index.rb", "rubygems/user_interaction.rb", "forwardable.rb", "rubygems/specification.rb", "date.rb", "rational.rb", "date/format.rb", "rubygems/version.rb", "rubygems/custom_require.rb"]

···

On Jan 17, 2006, at 4:44 PM, Guillaume Marcais wrote:

Is it true that RubyGems requires mathn? It seems so to me:

gus@guslaptop ~]ruby -e 'p(5.lcm(3))'
-e:1: undefined method `lcm' for 5:Fixnum (NoMethodError)
gus@guslaptop ~]ruby -rubygems -e 'p(5.lcm(3))'
15
gus@guslaptop ~]ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]
gus@guslaptop ~]gem -v
0.8.11

That gives me somewhat of an uneasy feeling. How many core tampering libraries does RubyGems requires that may make me rely on methods which are not really in the core?

Guillaume.

Tom Allison wrote:

Jules wrote:

No, you don't have to require integer, because it is in the core. The core is always available. You can read the docs here:

RDoc Documentation

And there is a standard library too:

RDoc Documentation

Most of these are not available by default. If you want to use a YAML parser, you have to require YAML.

Thanks for the references.
For some reason I can't get my installation of Ruby to do what the examples show:
6.lcm 7
return
>> 6.lcm 7
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):17
        from :0
>> 6.lcm(7)
NoMethodError: undefined method `lcm' for 6:Fixnum
        from (irb):18
        from :0
This is too simple to get wrong?

Guillaume Marcais wrote:

Is it true that RubyGems requires mathn? It seems so to me:

No, it does not.

  $ ruby -rubygems -e 'p $".include?("mathn.rb")'
  false

But it does require 'time',
which requires 'parsedate',
which requires 'date/format',
which requires 'rational',
which adds the 'lcm' method).

Any of the standard libraries (e.g. time, parsedate, time/format) may
load things that you haven't explicitly asked for.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Ah, so the documentation isn't wrong, it's just confusing.

Tom, the issue is that Ruby allows different libraries to modify and extend the same class. (So, Integer has a base set of methods included in the core, but including libraries like Rational adds additional methods.) Ruby's documentation system (RDoc) has the ability to conveniently merge the methods from all those libraries under the single class to which they belong. Unfortunately, it doesn't make clear which file or library each method comes from, and the people who wrote the documentation for these 'addon' methods did not make clear which library they came from.

Your confusion is certainly understandable.

···

On Jan 16, 2006, at 8:05 AM, Daniel Harple wrote:

On Jan 16, 2006, at 4:01 PM, Daniel Harple wrote:

You must require 'mathn'

Actually, this is partially wrong. #lcm is defined in rational, but mathn requires rational. So require 'rational', but require 'mathn' works too. Sorry.

Err. Mind the terms, including a module in Ruby is something VERY different from requiring a library.

Heavy spoonfeeding follows.

That said, a large majority of libraries are named according to the modules / classes defined in them. E.g.: A class named Toys::Fluffy::Teddy will be very probably defined in a file called "toys/fluffy/teddy.rb" relative to somewhere on your Ruby library path.

However, that is only a convention, and is not enforced. Some libraries, like "mathn", don't define any new modules or classes, but instead (ab)use the metaprogramming and reflective capacities of Ruby and modify existing modules / classes by defining new methods or changing the behaviour of existing ones.

ri only looks up information on modules, classes, and methods in whatever libraries were merged in your documentation, it doesn't know anything about libraries. The HTML backend to rdoc stores generally more information, like library synopses, source file names, and required files. Personally, I prefer only the Ruby core doeumentation available for ri, where problems with what required what when aren't an issue, and look up libraries on the web.

Anyways, if you're still confused about something - or more confused than before - feel free to bug.

David Vallner

···

On Mon, 16 Jan 2006 16:12:15 +0100, Tom Allison <tallison@tacocat.net> wrote:

Daniel Harple wrote:

On Jan 16, 2006, at 3:50 PM, Tom Allison wrote:

This is too simple to get wrong?

  You must require 'mathn'
example:
require 'mathn'
6.lcm(7) # -> 42
- Daniel

Thank you. This is the first I've heard of mathn, even from the Integer doc pages. I missed it.

Backing up....

I was assuming that to include a module I would call the class name on the assumption that the class name matches the class file (similar to perl and java). But this isn't the case with mathn.

Doing some more poking about:
ri has nothing known about mathn or anything like it.
ri tells me that Integer.lcm is a real method.
but to invoke this method on a Fixnum, I have to require a package name that isn't mentioned in the lcm, Fixnu, or Integer docs.

Granted, I found all this from the web pages for the standard library, but it wasn't intuitive. It doesn't even mention that mathn is responsible for this lcm method.

This is really frustrating. Is the documentation wrong or did I just miss something that every Ruby-ite should know?

Gavin Kistner wrote:

You must require 'mathn'

Actually, this is partially wrong. #lcm is defined in rational, but mathn requires rational. So require 'rational', but require 'mathn' works too. Sorry.

Ah, so the documentation isn't wrong, it's just confusing.

Tom, the issue is that Ruby allows different libraries to modify and extend the same class. (So, Integer has a base set of methods included in the core, but including libraries like Rational adds additional methods.) Ruby's documentation system (RDoc) has the ability to conveniently merge the methods from all those libraries under the single class to which they belong. Unfortunately, it doesn't make clear which file or library each method comes from, and the people who wrote the documentation for these 'addon' methods did not make clear which library they came from.

Your confusion is certainly understandable.

OK, I understand how the documentation got there. It's a merged super set of all the methods from all the libraries. Makes sense.

But it would be *really* useful if there was something in the docs to delineate where methods come from if they aren't provided in the core.

Otherwise you end up with people like me who have a lot less hair on either side of their head.

How would I go about identifying something like this in the future? Where I find an ri documented method that isn't in the core.
http://www.ruby-doc.org/stdlib/
by itself doesn't provide enough information unless I just poke around the table of contents hoping to get lucky.

···

On Jan 16, 2006, at 8:05 AM, Daniel Harple wrote:

On Jan 16, 2006, at 4:01 PM, Daniel Harple wrote:

David Vallner wrote:

Err. Mind the terms, including a module in Ruby is something VERY different from requiring a library.

My mix in terminology is a reflection of my origins. Perl uses Modules.

Heavy spoonfeeding follows.

That said, a large majority of libraries are named according to the modules / classes defined in them. E.g.: A class named Toys::Fluffy::Teddy will be very probably defined in a file called "toys/fluffy/teddy.rb" relative to somewhere on your Ruby library path.

I like this idea. Obviously because it's so very perl-ish.
But it also makes sense.

However, that is only a convention, and is not enforced. Some libraries, like "mathn", don't define any new modules or classes, but instead (ab)use the metaprogramming and reflective capacities of Ruby and modify existing modules / classes by defining new methods or changing the behaviour of existing ones.

This should be discouraged or at least a consistent alternative. In any event, if it were possible to identify methods that require more than the stdlib or core....

Anyways, if you're still confused about something - or more confused than before - feel free to bug.

Not so much anymore, just more cautious.
I like what I've seen so far but my lack of familiarity makes everything seem so shockingly bizarre at times. I have to check myself to make sure.

Thanks. This has been a lesson.

Two tricks helped me to determine where the method is defined:

1) Every rdoc page mentions at the top which files the methods are
defined in. For example, the Integer core rdoc page[1] has the
following near the top:

   Class Integer
   In: numeric.c
           lib/rational.rb
   Parent: Numeric

From the file it's often possible to guess the library. In this case,
the header doesn't tell us enough to be sure whether lcm is coming
from; from numeric.c (ie. inheritance from Numeric) or
lib/rational.rb.

2) Going to the documentation for the actual method[2], you can click
on the method name and it will show you the source for the method[3],
preceded by a comment telling you the file name and line number[4].
Having narrowed it down to one file, we can again try to guess the
library name.

I'll agree with you that it should be easier to determine the library
that defined the method. But in the meantime, these tricks can help.

Jacob Fugal

[1] class Integer - RDoc Documentation
[2] class Integer - RDoc Documentation
[3] http://www.ruby-doc.org/core/classes/Integer.src/M000283.html

[4] At least for the methods I checked. lcm has it. A few other of the
pure ruby methods had it. Some C methods I checked didn't, but seeing
that they were C was enough to give them away. YMMV.

···

On 1/16/06, Tom Allison <tallison@tacocat.net> wrote:

But it would be *really* useful if there was something in the docs to
delineate where methods come from if they aren't provided in the core.

David Vallner wrote:

[snip]

However, that is only a convention, and is not enforced. Some libraries, like "mathn", don't define any new modules or classes, but instead (ab)use the metaprogramming and reflective capacities of Ruby and modify existing modules / classes by defining new methods or changing the behaviour of existing ones.

This should be discouraged or at least a consistent alternative. In any event, if it were possible to identify methods that require more than the stdlib or core....

Good luck finding support for that. Of course, noone dabbles into this sort of voodoo without his metaprogramming helmet. Banging your head against the wall in frustration at stuff not working can result in severe head trauma. Ruby allows you to do this sort of magic, and do it definately more easily and cleanly than in other languages directly manipulating superclass lists and property dictionaries and all such foolishness. This is a very distinctive feature of Ruby, and no chance in hell it's getting nerfed or discouraged. It's runninf with scissors, but sometimes you need to cut something really quickly :wink:

That said, libraries that alter what is already present in other namespaces are VERY rare. Not actively discouraged in the least, but rare.

And if you use HTML documentation, you can distinguish what was defined where, as was previously mentioned.

Anyways, if you're still confused about something - or more confused than before - feel free to bug.

Not so much anymore, just more cautious.
I like what I've seen so far but my lack of familiarity makes everything seem so shockingly bizarre at times. I have to check myself to make sure.

Takes getting used to, 's all.

David Vallner

···

On Mon, 16 Jan 2006 22:27:37 +0100, Tom Allison <tallison@tacocat.net> wrote:

Hi --

David Vallner wrote:

[snip]

However, that is only a convention, and is not enforced. Some libraries, like "mathn", don't define any new modules or classes, but instead (ab)use the metaprogramming and reflective capacities of Ruby and modify existing modules / classes by defining new methods or changing the behaviour of existing ones.

This should be discouraged or at least a consistent alternative. In any event, if it were possible to identify methods that require more than the stdlib or core....

Good luck finding support for that. Of course, noone dabbles into
this sort of voodoo without his metaprogramming helmet. Banging your
head against the wall in frustration at stuff not working can result
in severe head trauma. Ruby allows you to do this sort of magic,
and do it definately more easily and cleanly than in other languages
directly manipulating superclass lists and property dictionaries and
all such foolishness. This is a very distinctive feature of Ruby,
and no chance in hell it's getting nerfed or discouraged. It's
runninf with scissors, but sometimes you need to cut something
really quickly :wink:

mathn is in the standard library, so it's got a different relation to
the rest of the distribution than a third-party library would.

That said, libraries that alter what is already present in other
namespaces are VERY rare. Not actively discouraged in the least, but
rare.

It depends what you mean by actively. Dozens of people have certainly
counseled against it, over the years. The difficulty, for me, has
always been how to harness this particular kind of flexibility and
openness, a prospect I've always found more intriguing than the
prospect of just deciding that it exists for the purpose of being
avoided. I think that if Ruby 2.0 has selector namespaces, we'll
probably see some very creative and productive runtime class changing.

Or maybe not. I've heard extremely little about anyone actually using
any of the libraries that make block-scoped core changes possible.
Maybe there isn't all that great a demand for orderly ways to do it.

David

···

On Tue, 17 Jan 2006, David Vallner wrote:

On Mon, 16 Jan 2006 22:27:37 +0100, Tom Allison <tallison@tacocat.net> wrote:

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!