Ruby Basics

R

Ralph Grothe

Hello,

I successfully compiled and installed Ruby and Gems on this HP-UX box
(see my other thread).

Yesterday, I bought a copy of the Ruby equivalent to the Perl Camel Book
(n.b. I am coming from Perl), viz. the PickAxe Book,
and read the first couple of chapters while toying parallel a little bit
at the irb>

That's where my first question arose.
Being used to the Perl debugger for similar experiments like with irb,
the former at least offers, albeit moderate, history amenities (viz.
!cmd#, to repeat cmd No. #)
I would have expected irb to offer some readline and thus command
history support (I am a lousy typer)?

Then while reading the code examples in the PickAxe I was a little
bewildered
how the authors were merrily extending their sample classes by simply
redifinig some method to add functionality without, as I would have
expected,
first sublassing the class and then overriding single methods.

Instead it went like this

E.g.

class Noise
def moo
# some implementation
end
end

# more paragraphs of text
# and then taking up again

class Noise
def moo
# deviating implementation from first definition
end
end

# and so forth


I this valid (and recommnded) Ruby, or were they just
sweeping former stuff under the carpet to keep the sample code terse?

Similarily, I was puzzled that it seems to be possible to
again extend base classes like Array without being required to subclass
and override, instead doing something like

class Array
def my_super_sort
# implementation
end
end

Is this really all that easy?

As for style, shouldn't Ruby class definitions just as one
class-end block go into a single file instead of these break ups?

named as the class
 
S

Stefano Crocco

Alle marted=C3=AC 24 luglio 2007, Ralph Grothe ha scritto:
Hello,

I successfully compiled and installed Ruby and Gems on this HP-UX box
(see my other thread).

Yesterday, I bought a copy of the Ruby equivalent to the Perl Camel Book
(n.b. I am coming from Perl), viz. the PickAxe Book,
and read the first couple of chapters while toying parallel a little bit
at the irb>

That's where my first question arose.
Being used to the Perl debugger for similar experiments like with irb,
the former at least offers, albeit moderate, history amenities (viz.
!cmd#, to repeat cmd No. #)
I would have expected irb to offer some readline and thus command
history support (I am a lousy typer)?

irb does have readline support, but it's not enabled by default. One way to=
do=20
this is to pass the --readline option to irb (see irb -h for other options)=
=2E=20
According to the first version of the pickaxe (I don't have the second one)=
,=20
you should be able to do this also by setting IRB.conf[:USE_READLINE] to tr=
ue=20
in your .irbrc, but I'm not sure this information is up to date. Since you=
=20
just bought the book you can look there for more information. Another=20
possibility is to use wirble (http://raa.ruby-lang.org/project/wirble/).
Then while reading the code examples in the PickAxe I was a little
bewildered
how the authors were merrily extending their sample classes by simply
redifinig some method to add functionality without, as I would have
expected,
first sublassing the class and then overriding single methods.

Instead it went like this

E.g.

class Noise
def moo
# some implementation
end
end

# more paragraphs of text
# and then taking up again

class Noise
def moo
# deviating implementation from first definition
end
end

# and so forth


I this valid (and recommnded) Ruby, or were they just
sweeping former stuff under the carpet to keep the sample code terse?

If I understand correctly your question, I'd say it's the latter.
You can't add functionality to a method by redefining it: redefining a meth=
od=20
overwrites the previous definition:

class C

def a_method
puts "this is the first definition"
end

def a_method
puts "this is the first definition"
end

end

C.new.a_method
=3D> "this is the second definition"

On the other hand, you can reopen a class to add other methods or constants=
=20
(or to redefine already defined methods):

class C

def method_1
puts "this is method_1"
end

end

# some other code

class C
=20
def method_2
puts "this is method_2"
end

end

C.new.method_1
=3D> "this is method_1"

C.new.method_2
=3D> "this is method_2"
Similarily, I was puzzled that it seems to be possible to
again extend base classes like Array without being required to subclass
and override, instead doing something like

class Array
def my_super_sort
# implementation
end
end

Is this really all that easy?

It is, but you need to be careful. If you only want to add new methods, the=
n=20
it's most likely ok, but if you want to modify already existing methods, th=
en=20
you can get in trouble, because other libraries (including the ruby standar=
d=20
library) expect those methods to behave in a certain way and will break if=
=20
they don't.
As for style, shouldn't Ruby class definitions just as one
class-end block go into a single file instead of these break ups?

Usually, a class definition is indeed a single class/end block in a single=
=20
file. They're broken up only if there is some reason to do it.
named as the class

Stefano
 
T

Todd Benson


That's where my first question arose.
Being used to the Perl debugger for similar experiments like with irb,
the former at least offers, albeit moderate, history amenities (viz.
!cmd#, to repeat cmd No. #)
I would have expected irb to offer some readline and thus command
history support (I am a lousy typer)?

It should. Did you compile with readline (you need to have
lib-readline of course).
Then while reading the code examples in the PickAxe I was a little
bewildered
how the authors were merrily extending their sample classes by simply
redifinig some method to add functionality without, as I would have
expected,
first sublassing the class and then overriding single methods.

Instead it went like this

E.g.

class Noise
def moo
# some implementation
end
end

# more paragraphs of text
# and then taking up again

class Noise
def moo
# deviating implementation from first definition
end
end

# and so forth


I this valid (and recommnded) Ruby, or were they just
sweeping former stuff under the carpet to keep the sample code terse?
Similarily, I was puzzled that it seems to be possible to
again extend base classes like Array without being required to subclass
and override, instead doing something like

class Array
def my_super_sort
# implementation
end
end

Is this really all that easy?

Yes, but as in all easy things, there are caveats.

You can 'open' up any class, and, in fact, any object whenever you want.

irb> a = "hello"
=> "hello"
irb> b = "hajimemashite"
=> "hajimemashite"
irb> a.class
=> String
irb> b.class
=> String
irb> class String; def welcome_f; puts self + ", welcome to f method!"; end; end
=> nil
irb> a.welcome_f
hello, welcome to f method!
=> nil
irb> b.welcome_f
hajimemashite, welcome to f method!
irb> def a.welcome_g; puts self + ", welcome to g method!"; end; end
=> nil
irb> a.welcome_g
hello, welcome to g method!
=> nil
irb> b.welcome_g
NoMethodError: undefined method 'g' for "hajimemashite":String

The welcome_g method for the object a is called a singleton method.
It applies only to a.

There are obvious risks in opening up core classes (like String),
especially if you modify them instead of just adding to them. Even
adding to classes after the fact is somewhat dangerous because of
possible clashes with gems that you use, or sometimes even with your
own code!
As for style, shouldn't Ruby class definitions just as one
class-end block go into a single file instead of these break ups?

That's almost certainly up to you.

hth a little,
Todd
 
C

Chris Lowis

I would have expected irb to offer some readline and thus command
history support (I am a lousy typer)?

You can get command history by installing the wirble gem

sudo gem install wirble

and adding the following to your ~/.irbrc file

# load libraries
require 'rubygems'
require 'wirble'

# start wirble (with color)
Wirble.init
Wirble.colorize

More information on wirble here :
http://pablotron.org/software/wirble/
Is this really all that easy?

My understanding is that it is this easy !

You might also find the following interesting :
http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-perl/

Regards,

Chris
 
R

Ralph Grothe

Chris said:
You can get command history by installing the wirble gem

sudo gem install wirble

and adding the following to your ~/.irbrc file

# load libraries
require 'rubygems'
require 'wirble'

# start wirble (with color)
Wirble.init
Wirble.colorize

More information on wirble here :
http://pablotron.org/software/wirble/


My understanding is that it is this easy !

You might also find the following interesting :
http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-perl/

Regards,

Chris


Hi Chris,

many thanks for the quick response and the valuable hint for the wirble
gem.
As I have to leave now, it will be the first thing that I try tomorrow
and give feedback.

As for Gems configuration.
Do you have any idea where and how I would have to put our proxy
informations (url, port, credentials) so that I could query Internet
Gems repositories?
I tried the -p http://proxy_user:[email protected]:proxy_port
switch with the gem list command but it didn't work.
So I sought for a config file like I am used to with the Perl
CPAN/Config.pm
but couldn't find something comparable beneath the gems tree.

I start to like Ruby.
I only need to get used to Ruby idioms and doing things the Ruby way
instead of taking over habits from Perl.
But since I so far lack knowledge of all the methods
(although some_object.methods.sort in irb is a tremendous help) it takes
some
time to discover.
 
R

Ralph Grothe

Stefano said:
Alle martedì 24 luglio 2007, Ralph Grothe ha scritto:
That's where my first question arose.
Being used to the Perl debugger for similar experiments like with irb,
the former at least offers, albeit moderate, history amenities (viz.
!cmd#, to repeat cmd No. #)
I would have expected irb to offer some readline and thus command
history support (I am a lousy typer)?

irb does have readline support, but it's not enabled by default. One way
to do
this is to pass the --readline option to irb (see irb -h for other
options).
According to the first version of the pickaxe (I don't have the second
one),
you should be able to do this also by setting IRB.conf[:USE_READLINE] to
true
in your .irbrc, but I'm not sure this information is up to date. Since
you
just bought the book you can look there for more information. Another
possibility is to use wirble (http://raa.ruby-lang.org/project/wirble/).

Hi Stefano,

I fear my ruby build on hpux doesn't currently contain readline support
because I wasn't aware that I obviously was required to signal make that
I wished so.
When I start irb with --readline it doesn't seem to show any effect
(e.g. promoted tab completion or command history missing)
Although I am a lucky owner of the 2nd ed. of Pickaxe (which cover Ruby
1.8)
I haven't yet come accross every chapter despite occassional flipping
(it's such a tome)
In my volume chpt. 15 deals on IRB, but I haven't yet fumbled up a
$HOME/.irbrc
let alone hacked the IRB class.

How can I verify if my ruby build lacks or supplies readline support?

I came accross that Config module (btw, Perl has a namesake which
imports per default (I see Rubyists frown upon such namespace pollution)
a tied hash called %Config).
So I hoped to find, case ignoring, any key that hopefully somewhat
intuitively named by this module's author could contain the string read.
But this futile attempt doesn't hit:

$ ruby -r rbconfig -e 'include Config;puts
CONFIG.keys.grep(/read/i).sort.join("\n")'

Btw, not having delved into the Modules chapter yet,
why am I supposed to require *and* include here?

If I understand correctly your question, I'd say it's the latter.
You can't add functionality to a method by redefining it: redefining a
method
overwrites the previous definition:

Well, I am by far no OO expert, and Perl's OO implementation
of OO is very liberal indeed for the Purists' taste.

But redefination of a method from a derived class is actually what you
do,
if you aren't please with its functionality, so I thought.
While those methods you are happy with you simply inherit.

class C

def a_method
puts "this is the first definition"
end

def a_method
puts "this is the first definition"
end

I asume a typo here,
you probably meant "this is the second definition"?
end

C.new.a_method
=> "this is the second definition"

On the other hand, you can reopen a class to add other methods or
constants
(or to redefine already defined methods):


Well, I think what confused me is the "strange" terminology.
I simply didn't know the concept of "reopening a class".
class C

def method_1
puts "this is method_1"
end

end

# some other code

class C

def method_2
puts "this is method_2"
end

end

C.new.method_1
=> "this is method_1"

C.new.method_2
=> "this is method_2"

It is, but you need to be careful. If you only want to add new methods,
then
it's most likely ok, but if you want to modify already existing methods,
then
you can get in trouble, because other libraries (including the ruby
standard
library) expect those methods to behave in a certain way and will break
if
they don't.

I won't be doing this, at least for quite some while until I
master Ruby enough (will I ever?).
 
R

Ralph Grothe

Todd said:
It should. Did you compile with readline (you need to have
lib-readline of course).

Hi Todd,

please see my response to Stefano's reply.

Yes, but as in all easy things, there are caveats.

You can 'open' up any class, and, in fact, any object whenever you want.

This "opening" sounded rather unfamiliar to me.
irb> a = "hello"
=> "hello"
irb> b = "hajimemashite"
=> "hajimemashite"
irb> a.class
=> String
irb> b.class
=> String
irb> class String; def welcome_f; puts self + ", welcome to f method!";
end; end
=> nil
irb> a.welcome_f
hello, welcome to f method!
=> nil
irb> b.welcome_f
hajimemashite, welcome to f method!
irb> def a.welcome_g; puts self + ", welcome to g method!"; end; end
=> nil

I can't find the opening class statement that seems to belong to the the
2nd "end".
Or is irb so forgiving?
But interesting here seems to be that you explicitly specify the object
"a" as "receiver" in your definition of method welcome_g.
Is this what makes it a "singleton"?
I haven't yet read enough about this concept.
In some way it looks to me as some sort of privatizing data an methods
to a certain object (what sets it apart from the "private" protector?).
irb> a.welcome_g
hello, welcome to g method!
=> nil
irb> b.welcome_g
NoMethodError: undefined method 'g' for "hajimemashite":String

The welcome_g method for the object a is called a singleton method.
It applies only to a.

There are obvious risks in opening up core classes (like String),
especially if you modify them instead of just adding to them. Even
adding to classes after the fact is somewhat dangerous because of
possible clashes with gems that you use, or sometimes even with your
own code!

As already replied to Stefano,
it will certainly take quite a while until I would be confident enough
to mess about with core classes.
That's almost certainly up to you.

Yes, but don't Rubyists promote a certain style guide?
(Perlists are pretty picky about it, contrary to the language's public
conception)
 
R

Ralph Grothe

Here's the full contents of the Config hash of my Ruby installation:

$ ruby -r rbconfig -e 'include Config;CONFIG.sort.each {|k,v| printf("%s
=> %s\n",k,v)}'

ALLOCA =>
AR => ar
ARCHFILE =>
ARCH_FLAG =>
AS => as
ASFLAGS =>
CC => /opt/ansic/bin/cc
CCDLFLAGS => +Z
CFLAGS => -g
COMMON_HEADERS =>
COMMON_LIBS =>
COMMON_MACROS =>
CP => cp
CPP => /opt/ansic/bin/cc -E
CPPFLAGS =>
CPPOUTFILE => -o conftest.i
DESTDIR =>
DLDFLAGS => -E
DLDLIBS => -lc
DLEXT => sl
DLEXT2 =>
DLLWRAP =>
ECHO_C => \\c
ECHO_N =>
ECHO_T =>
EGREP => /usr/bin/grep -E
ENABLE_SHARED => no
EXEEXT =>
EXPORT_PREFIX =>
EXTOUT => .ext
EXTSTATIC =>
GNU_LD => no
GREP => /usr/bin/grep
INSTALL => /opt/imake/bin/install -c
INSTALL_DATA => /opt/imake/bin/install -c -m 644
INSTALL_PROGRAM => /opt/imake/bin/install -c
INSTALL_SCRIPT => /opt/imake/bin/install -c
LDFLAGS =>
LDSHARED => ld -b
LIBEXT => a
LIBPATHENV => SHLIB_PATH
LIBPATHFLAG => -L"%s"
LIBRUBY => libruby-static.a
LIBRUBYARG => -lruby-static
LIBRUBYARG_SHARED =>
LIBRUBYARG_STATIC => -lruby-static
LIBRUBY_A => libruby-static.a
LIBRUBY_ALIASES => libruby.so
LIBRUBY_DLDFLAGS => -E
LIBRUBY_LDSHARED => ld -b
LIBRUBY_SO => libruby.so.1.8.6
LIBS => -ldld -lcrypt -lm
LINK_SO =>
LN_S => ln -s
MAINLIBS =>
MAJOR => 1
MAKEDIRS => mkdir -p
MAKEFILES => Makefile
MANTYPE => man
MINIRUBY => ./miniruby
MINOR => 8
NM =>
NROFF => /usr/bin/nroff
OBJDUMP =>
OBJEXT => o
OUTFLAG => -o
PACKAGE_BUGREPORT =>
PACKAGE_NAME =>
PACKAGE_STRING =>
PACKAGE_TARNAME =>
PACKAGE_VERSION =>
PATH_SEPARATOR => :
PREP => miniruby
RANLIB => ranlib
RDOCTARGET =>
RM => rm -f
RPATHFLAG =>
RUBYW_INSTALL_NAME =>
RUBY_INSTALL_NAME => ruby
RUBY_SO_NAME => ruby
RUNRUBY => ./miniruby $(srcdir)/runruby.rb --extout=.ext --
SET_MAKE =>
SHELL => /bin/sh
SOLIBS =>
STATIC =>
STRIP => strip
TEENY => 6
TRY_LINK =>
WINDRES =>
XCFLAGS => -DRUBY_EXPORT
XLDFLAGS => -Wl,-E -L.
YACC => bison -y
YFLAGS =>
arch => hppa2.0w-hpux11.11
archdir => /usr/local/lib/ruby/1.8/hppa2.0w-hpux11.11
bindir => /usr/local/bin
build => hppa2.0w-hp-hpux11.11
build_alias =>
build_cpu => hppa2.0w
build_os => hpux11.11
build_vendor => hp
configure_args => '--with-zlib-dir=/opt/iexpress/zlib'
'--with-openssl-dir=/opt/openssl/0.9.7' 'CC=/opt/ansic/bin/cc'
datadir => /usr/local/share
datarootdir => /usr/local/share
docdir => /usr/local/share/doc/$(PACKAGE)
dvidir => /usr/local/share/doc/$(PACKAGE)
exec_prefix => /usr/local
host => hppa2.0w-hp-hpux11.11
host_alias =>
host_cpu => hppa2.0w
host_os => hpux11.11
host_vendor => hp
htmldir => /usr/local/share/doc/$(PACKAGE)
includedir => /usr/local/include
infodir => /usr/local/share/info
libdir => /usr/local/lib
libexecdir => /usr/local/libexec
localedir => /usr/local/share/locale
localstatedir => /usr/local/var
mandir => /usr/local/share/man
oldincludedir => /usr/include
pdfdir => /usr/local/share/doc/$(PACKAGE)
prefix => /usr/local
psdir => /usr/local/share/doc/$(PACKAGE)
ruby_install_name => ruby
ruby_version => 1.8
rubylibdir => /usr/local/lib/ruby/1.8
rubyw_install_name =>
sbindir => /usr/local/sbin
setup => Setup
sharedstatedir => /usr/local/com
sitearch => hppa2.0w-hpux11.11
sitearchdir => /usr/local/lib/ruby/site_ruby/1.8/hppa2.0w-hpux11.11
sitedir => /usr/local/lib/ruby/site_ruby
sitelibdir => /usr/local/lib/ruby/site_ruby/1.8
sysconfdir => /usr/local/etc
target => hppa2.0w-hp-hpux11.11
target_alias =>
target_cpu => hppa2.0w
target_os => hpux11.11
target_vendor => hp
topdir => /usr/local/lib/ruby/1.8/hppa2.0w-hpux11.11
 
R

Robert Klemme

2007/7/26 said:
Yes, but don't Rubyists promote a certain style guide?
(Perlists are pretty picky about it, contrary to the language's public
conception)

Well, there are *some* style rules but not with respect to how many
times you open and close classes. Actually there are cases (i.e. when
modifying lib classes like String etc.) where it is the only realistic
option to open it in your script and add a few methods.

Kind regards

robert
 
T

Todd Benson

Hi Todd,

please see my response to Stefano's reply.

Look at your mkmf.log file at said:
This "opening" sounded rather unfamiliar to me.

I can't find the opening class statement that seems to belong to the the
2nd "end".

First "end" is for the "def". Second "end" is for the "class".
Or is irb so forgiving?
But interesting here seems to be that you explicitly specify the object
"a" as "receiver" in your definition of method welcome_g.
Is this what makes it a "singleton"?

Sort of. It makes the method a singleton method, and makes "a" an
instance of a singleton. At least, that's the way I understand it.
I haven't yet read enough about this concept.
In some way it looks to me as some sort of privatizing data an methods
to a certain object (what sets it apart from the "private" protector?).

"private" just restricts access of methods to solely the object. As
you can see, there is no restriction with the welcome_f or welcome_g
methods. If they were private, my attempt to call them would raise an
error.
As already replied to Stefano,
it will certainly take quite a while until I would be confident enough
to mess about with core classes.

Mess away. You won't permanently hurt anything (unless you ditribute
your code to some unwary users, of course :).

As for style, a general rule of thumb is that you don't open already
defined classes, and if you do, it's usually to add functionality, not
modify it.
Yes, but don't Rubyists promote a certain style guide?
(Perlists are pretty picky about it, contrary to the language's public
conception)

If you are worried about style, just look at some code from the RAA
site or the rubyforge site for examples.

cheers,
Todd
 
T

Todd Benson

First "end" is for the "def". Second "end" is for the "class".

My bad! The second "end" for the second "def" statement is a mistake!
I thought you were asking about the first def. My apologies.

Todd
 

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,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top