ruby user's guide

Upload: may398

Post on 05-Apr-2018

249 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/31/2019 Ruby User's Guide

    1/68

    y User's Guide - About the guide 1 1

    eHome Workstation 2006/10/29 07:46

    About the guide

    This introductory user's guide is mirrored in various places and is available in several translations. Thecurrent English language version is kept onrubyist.net. If you come across an out-of-date version, pleasenotify the webmaster where the mirror is hosted.

    Original Japanese version bymatz.First English translationby GOTO Kentaro& Julian Fondren.Re-translation and added material byMark Slagell.

    Page 1 :

  • 7/31/2019 Ruby User's Guide

    2/68

    y User's Guide - Contents & Chapters 1 1

    eHome Workstation 2006/10/29 07:46

    Contents & Chapters

    Ruby is "an interpreted scripting language for quick and easy object-oriented programming"

    1. What is ruby? 2. Getting started

    3. Simple examples

    4. Strings

    5. Regular expressions

    6. Arrays

    7. Back to the simple examples

    8. Control structures

    9. Iterators

    10. Object-oriented thinking

    11. Methods

    12. Classes

    13. Inheritance

    14. Redefinition of methods

    15. Access control

    16. Singleton methods 17. Modules

    18. Procedure objects

    19. Variables

    20. Global variables

    21. Instance variables

    22. Local variables

    23. Class constants

    24. Exception processing: rescue

    25. Exception processing: ensure

    26. Accessors

    27. Object initialization

    28. Nuts and bolts

    About the guide

    Page 2 :

  • 7/31/2019 Ruby User's Guide

    3/68

    y User's Guide - What is ruby? 1 1

    eHome Workstation 2006/10/29 07:44

    What is ruby?

    Ruby is "an interpreted scripting language for quick and easy object-oriented programming" -- what does thismean?

    interpreted scripting language:

    ability to make operating system calls directlypowerful string operations and regular expressionsimmediate feedback during development

    quick and easy:

    variable declarations are unnecessary

    variables are not typedsyntax is simple and consistentmemory management is automatic

    object oriented programming:

    everything is an objectclasses, methods, inheritance, etc.singleton methods"mixin" functionality by moduleiterators and closures

    also:

    multiple precision integersconvenient exception processingdynamic loadingthreading support

    If you are unfamiliar with some of the concepts above, read on, and don't worry. The mantra of the rubylanguage is quick and easy .

    Page 3 :

  • 7/31/2019 Ruby User's Guide

    4/68

    y User's Guide - Getting started 1 1

    eHome Workstation 2006/10/29 07:44

    Getting started

    First, you'll want to check whether ruby is installed. From the shell prompt (denoted here by "", so don'ttype the ), type

    % r uby - v

    ( tells the interpreter to print the version of ruby), then press the Enter key. If ruby is installed, you willsee a message something like the following:

    % r uby - vr uby 1. 8. 3 ( 2005- 09- 21) [ i 586- l i nux ]

    If ruby is not installed, you can ask your administrator to install it, or you can do it yourself, since ruby isfree software with no restrictions on its installation or use.

    Now, let's play with ruby. You can place a ruby program directly on the command line using the option:

    % r uby - e ' put s " hel l o wor l d" 'hel l o wor l d

    More conventionally, a ruby program can be stored in a file.

    % echo " put s ' hel l o wor l d' " > hel l o. r b% r uby hel l o. r bhel l o wor l d

    When writing more substantial code than this, you will want to use a real text editor!

    Some surprisingly complex and useful things can be done with miniature programs that fit in a command

    line. For example, this one replaces with in all C source and header files in the current workingdirectory, backing up the original files with ".bak" appended:

    % r uby - i . bak - pe ' sub " f oo" , " bar " ' * . [ ch]

    This program works like the UNIX command (but works slower than ):

    % r uby - pe 0 f i l e

    Page 4 :

  • 7/31/2019 Ruby User's Guide

    5/68

    y User's Guide - Simple examples 1 3

    eHome Workstation 2006/10/29 07:45

    Simple examples

    Let's write a function to compute factorials. The mathematical definition of factorial is:

    n! = 1 (when n==0)= n * (n-1)! (otherwise)

    In ruby, this can be written as:

    d e f f a c t ( n )i f n = = 0

    1e l s e

    n * f a c t ( n - 1 )e n d

    e n d

    You may notice the repeated occurrence of . Ruby has been called "Algol-like" because of this.(Actually, the syntax of ruby more closely mimics that of a langage named Eiffel.) You may also notice thelack of a statement. It is unneeded because a ruby function returns the last thing that was evaluatedin it. Use of a statement here is permissible but unnecessary.

    Let's try out our factorial function. Adding one line of code gives us a working program:

    # P r o g r a m t o f i n d t h e f a c t o r i a l o f a n u mb e r# Sa v e t h i s a s f a c t . r b

    d e f f a c t ( n )i f n = = 0

    1e l s e

    n * f a c t ( n - 1 )e n d

    e n d

    p u t s f a c t ( ARGV[ 0 ] . t o _ i )

    Here, is an array which contains the command line arguments, and converts a character string toan integer.

    % r u b y f a c t . r b 11% r u b y f a c t . r b 51 2 0

    Does it work with an argument of 40? It would make your calculator overflow...

    Page 5 :

  • 7/31/2019 Ruby User's Guide

    6/68

    y User's Guide - Simple examples 2 3

    eHome Workstation 2006/10/29 07:45

    % r u b y f a c t . r b 4 08 1 5 9 1 5 2 8 3 2 4 7 8 9 7 7 3 4 3 4 5 6 1 1 2 6 9 5 9 6 1 1 5 8 9 4 2 7 2 0 0 0 0 0 0 0 0 0

    It does work. Indeed, ruby can deal with any integer which is allowed by your machine's memory. So 400!can be calculated:

    % r u b y f a c t . r b 4 0 06 4 0 3 4 5 2 2 8 4 6 6 2 3 8 9 5 2 6 2 3 4 7 9 7 0 3 1 9 5 0 3 0 0 5 8 5 0 7 0 2 5 8 3 0 2 6 0 0 2 9 5 9 4 5 8 6 8 44 4 5 9 4 2 8 0 2 3 9 7 1 6 9 1 8 6 8 3 1 4 3 6 2 7 8 4 7 8 6 4 7 4 6 3 2 6 4 6 7 6 2 9 4 3 5 0 5 7 5 0 3 5 8 5 6 8 10 8 4 8 2 9 8 1 6 2 8 8 3 5 1 7 4 3 5 2 2 8 9 6 1 9 8 8 6 4 6 8 0 2 9 9 7 9 3 7 3 4 1 6 5 4 1 5 0 8 3 8 1 6 2 4 2 6 46 1 9 4 2 3 5 2 3 0 7 0 4 6 2 4 4 3 2 5 0 1 5 1 1 4 4 4 8 6 7 0 8 9 0 6 6 2 7 7 3 9 1 4 9 1 8 1 1 7 3 3 1 9 5 5 9 9 64 4 0 7 0 9 5 4 9 6 7 1 3 4 5 2 9 0 4 7 7 0 2 0 3 2 2 4 3 4 9 1 1 2 1 0 7 9 7 5 9 3 2 8 0 7 9 5 1 0 1 5 4 5 3 7 2 6 67 2 5 1 6 2 7 8 7 7 8 9 0 0 0 9 3 4 9 7 6 3 7 6 5 7 1 0 3 2 6 3 5 0 3 3 1 5 3 3 9 6 5 3 4 9 8 6 8 3 8 6 8 3 1 3 3 9 35 2 0 2 4 3 7 3 7 8 8 1 5 7 7 8 6 7 9 1 5 0 6 3 1 1 8 5 8 7 0 2 6 1 8 2 7 0 1 6 9 8 1 9 7 4 0 0 6 2 9 8 3 0 2 5 3 0 85 9 1 2 9 8 3 4 6 1 6 2 2 7 2 3 0 4 5 5 8 3 3 9 5 2 0 7 5 9 6 1 1 5 0 5 3 0 2 2 3 6 0 8 6 8 1 0 4 3 3 2 9 7 2 5 5 1 94 8 5 2 6 7 4 4 3 2 2 3 2 4 3 8 6 6 9 9 4 8 4 2 2 4 0 4 2 3 2 5 9 9 8 0 5 5 5 1 6 1 0 6 3 5 9 4 2 3 7 6 9 6 1 3 9 9 2

    3 1 9 1 7 1 3 4 0 6 3 8 5 8 9 9 6 5 3 7 9 7 0 1 4 7 8 2 7 2 0 6 6 0 6 3 2 0 2 1 7 3 7 9 4 7 2 0 1 0 3 2 1 3 5 6 6 2 46 1 3 8 0 9 0 7 7 9 4 2 3 0 4 5 9 7 3 6 0 6 9 9 5 6 7 5 9 5 8 3 6 0 9 6 1 5 8 7 1 5 1 2 9 9 1 3 8 2 2 2 8 6 5 7 8 5 79 5 4 9 3 6 1 6 1 7 6 5 4 4 8 0 4 5 3 2 2 2 0 0 7 8 2 5 8 1 8 4 0 0 8 4 8 4 3 6 4 1 5 5 9 1 2 2 9 4 5 4 2 7 5 3 8 4 80 3 5 5 8 3 7 4 5 1 8 0 2 2 6 7 5 9 0 0 0 6 1 3 9 9 5 6 0 1 4 5 5 9 5 2 0 6 1 2 7 2 1 1 1 9 2 9 1 8 1 0 5 0 3 2 4 9 10 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

    We cannot check the correctness at a glance, but it must be right. :-)

    When you invoke ruby with no arguments, it reads commands from standard input and executes them afterthe end of input:

    % r u b yp u t s " h e l l o wo r l d "p u t s " g o o d - b y e wo r l d "^ Dh e l l o wo r l d

    g o o d - b y e wo r l d

    The ^D above means control-D, a conventional way to signal end-of-input in a Unix context. InDOS/Windows, try pressing F6 or ^Z instead.

    Ruby also comes with a program called that allows you to enter ruby code from the keyboard in aninteractive loop, showing you the results as you go. It will be used extensively through the rest of this guide.

    If you have an ANSI-compliant terminal (this is almost certainly true if you are running some flavor of UNIX; under old versions of DOS you need to have installed or ; Windows XP,unfortunately, has now made this nearly impossible), you should use thisenhanced that adds visualindenting assistance, warning reports, and color highlighting. Otherwise, look in the subdirectory of the ruby distribution for the non-ANSI version that works on any terminal. Here is a short session:

    Page 6 :

  • 7/31/2019 Ruby User's Guide

    7/68

    y User's Guide - Simple examples 3 3

    eHome Workstation 2006/10/29 07:45

    % r u b y e v a l . r br u b y >He l l o , wo r l d .

    r u b y >

    is produced by . The next line, in this case , reports on whatever was last evaluated;ruby does not distinguish betweenstatements and expressions , so evaluating a piece of code basically meansthe same thing as executing it. Here, indicates that does not return a meaningful value. Note thatwe can leave this interpreter loop by saying , although still works too.

    Throughout this guide, " " denotes the input prompt for our useful little program.

    Page 7 :

  • 7/31/2019 Ruby User's Guide

    8/68

    y User's Guide - Strings 1 4

    eHome Workstation 2006/10/29 07:41

    Strings

    Page 8 :

  • 7/31/2019 Ruby User's Guide

    9/68

    y User's Guide - Strings 2 4

    eHome Workstation 2006/10/29 07:41

    Ruby deals with strings as well as numerical data. A string may be double-quoted ("...") or single-quoted('...').

    r u b y >

    r u b y >

    Double- and single-quoting have different effects in some cases. A double-quoted string allows characterescapes by a leading backslash, and the evaluation of embedded expressions using . A single-quotedstring does not do this interpreting; what you see is what you get. Examples:

    r u b y >abc

    r u b y >a \ n b \ n c

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Ruby's string handling is smarter and more intuitive than C's. For instance, you can concatenate strings with, and repeat a string many times with :

    r u b y >

    r u b y >

    Concatenating strings is much more awkward in C because of the need for explicit memory management:

    c h a r * s = ma l l o c ( s t r l e n ( s 1 ) + s t r l e n ( s 2 ) + 1 ) ;s t r c p y ( s , s 1 ) ;s t r c a t ( s , s 2 ) ; / * . . . * /

    Page 9 :

  • 7/31/2019 Ruby User's Guide

    10/68

    y User's Guide - Strings 3 4

    eHome Workstation 2006/10/29 07:41

    f r e e ( s ) ;

    But using ruby, we do not have to consider the space occupied by a string. We are free from all memorymanagement.

    Here are some things you can do with strings.

    Concatenation:

    r u b y >

    Repetition:

    r u b y >

    Extracting characters (note that characters are integers in ruby):

    r u b y >

    r u b y >

    (Negative indices mean offsets from the end of a string, rather than the beginning.)

    Extracting substrings:

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Testing for equality:

    r u b y >

    r u b y >

    Note: In ruby 1.0, results of the above are reported in uppercase, e.g. .

    Now, let's put some of these features to use. This puzzle is "guess the word," but perhaps the word "puzzle"

    Page 10 :

  • 7/31/2019 Ruby User's Guide

    11/68

    y User's Guide - Strings 4 4

    eHome Workstation 2006/10/29 07:41

    is too dignified for what is to follow

    # s a v e t h i s a s g u e s s . r bwo r d s = [ ' f o o b a r ' , ' b a z ' , ' q u u x ' ]s e c r e t = wo r d s [ r a n d ( 3 ) ]

    p r i n t " g u e s s ? "wh i l e g u e s s = ST DI N. g e t s

    g u e s s . c h o p !i f g u e s s = = s e c r e tp u t s " Yo u wi n ! "b r e a k

    e l s ep u t s " S o r r y , y o u l o s e . "

    e n dp r i n t " g u e s s ? "

    e n dp u t s " T h e wo r d wa s " , s e c r e t , " . "

    For now, don't worry too much about the details of this code. Here is what a run of the puzzle program lookslike.

    % r u b y g u e s s . r bg u e s s ? f o o b a rSo r r y , y o u l o s e .g u e s s ? q u u xSo r r y , y o u l o s e .g u e s s ? ^ DT h e wo r d wa s b a z .

    (I should have done a bit better, considering the 1/3 probability of success.)

    Page 11 :

  • 7/31/2019 Ruby User's Guide

    12/68

    y User's Guide - Regular expressions 1 3

    eHome Workstation 2006/10/29 07:43

    Regular expressions

    Let's put together a more interesting program. This time we test whether a string fits a description, encodedinto a concise pattern .

    There are some characters and character combinations that have special meaning in these patterns, including:

    range specificication (e.g., means a letter in the range to )

    letter or digit; same as

    neither letter or digit

    space character; same as

    non-space character

    digit character; same as

    non-digit character

    backspace (0x08) (only if in a range specification)

    word boundary (if not in a range specification)

    non-word boundary

    zero or more repetitions of the preceding

    one or more repetitions of the preceding

    at least m and at most n repetitions of the precedingat most one repetition of the preceding; same as

    either preceding or next expression may match

    grouping

    The common term for patterns that use this strange vocabulary is regular expressions . In ruby, as in Perl,they are generally surrounded by forward slashes rather than double quotes. If you have never worked withregular expressions before, they probably look anything but regular , but you would be wise to spend some

    time getting familiar with them. They have an efficient expressive power that will save you headaches (andmany lines of code) whenever you need to do pattern matching, searching, or other manipulations on textstrings.

    For example, suppose we want to test whether a string fits this description: "Starts with lower case f, whichis immediately followed by exactly one upper case letter, and optionally more junk after that, as long as thereare no more lower case characters." If you're an experienced C programmer, you've probably already writtenabout a dozen lines of code in your head, right? Admit it; you can hardly help yourself. But in ruby you needonly request that your string be tested against the regular expression .

    How about "Contains a hexadecimal number enclosed in angle brackets"? No problem.

    r u b y >|

    Page 12 :

  • 7/31/2019 Ruby User's Guide

    13/68

    y User's Guide - Regular expressions 2 3

    eHome Workstation 2006/10/29 07:43

    |n i l

    r u b y >f a l s e

    r u b y >f a l s e

    r u b y >f a l s e

    r u b y >t r u e

    Though regular expressions can be puzzling at first glance, you will quickly gain satisfaction in being able toexpress yourself so economically.

    Here is a little program to help you experiment with regular expressions. Store it as and run it bytyping at the command line.

    # Re q u i r e s a n ANSI t e r mi n a l !

    s t = " \ 0 3 3 [ 7 m"e n = " \ 0 3 3 [ m"

    p u t s " E n t e r a n e mp t y s t r i n g a t a n y t i me t o e x i t . "

    wh i l e t r u ep r i n t " s t r > " ; ST DOUT . f l u s h ; s t r = g e t s . c h o pb r e a k i f s t r . e mp t y ?p r i n t " p a t > " ; ST DOUT . f l u s h ; p a t = g e t s . c h o pb r e a k i f p a t . e mp t y ?r e = Re g e x p . n e w( p a t )p u t s s t r . g s u b ( r e , " # { s t } \ \ { e n } " )

    e n d

    The program requires input twice, once for a string and once for a regular expression. The string is testedagainst the regular expression, then displayed with all the matching parts highlighted in reverse video. Don'tmind details now; an analysis of this code will come soon.

    s t r > f o o b a rp a t > ^ f o +

    b a r~ ~ ~

    What you see above as red text will appear as reverse video in the program output. The "~~~" lines are for the benefit of those using text-based browsers.

    Let's try several more inputs.

    s t r > a b c 0 1 2 d b c d 5 5 5p a t > \ da b c d b c d

    Page 13 :

  • 7/31/2019 Ruby User's Guide

    14/68

    y User's Guide - Regular expressions 3 3

    eHome Workstation 2006/10/29 07:43

    If that surprised you, refer to the table at the top of this page: has no relationship to the character , butrather matches a single digit.

    What if there is more than one way to correctly match the pattern?

    s t r > f o o z b o o z e rp a t > f . * z

    e r~ ~ ~ ~ ~ ~ ~ ~

    is matched instead of just , since a regular expression maches the longest possible substring.

    Here is a pattern to isolate a colon-delimited time field.

    s t r > We d F e b 7 0 8 : 5 8 : 0 4 J S T 1 9 9 6p a t > [ 0 - 9 ] + : [ 0 - 9 ] + ( : [ 0 - 9 ] + ) ?

    We d F e b 7 J S T 1 9 9 6~ ~ ~ ~ ~ ~ ~ ~

    " " is a matching operator with respect to regular expressions; it returns the position in a string where amatch was found, or if the pattern did not match.

    r u b y >

    r u b y >

    Page 14 :

  • 7/31/2019 Ruby User's Guide

    15/68

    y User's Guide - Arrays 1 3

    eHome Workstation 2006/10/29 07:45

    Arrays

    Page 15 :

  • 7/31/2019 Ruby User's Guide

    16/68

    y User's Guide - Arrays 2 3

    eHome Workstation 2006/10/29 07:45

    You can create an array by listing some items within square brackets ( ) and separating them with commas.Ruby's arrays can accomodate diverse object types.

    r uby>

    Arrays can be concatenated or repeated just as strings can.

    r uby>

    r uby>

    We can use index numbers to refer to any part of a array.

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    (Negative indices mean offsets from the end of an array, rather than the beginning.)

    Arrays can be converted to and from strings, using and respecitvely:

    r uby>

    r uby>

    An associative array has elements that are accessed not by sequential index numbers, but by keys which canhave any sort of value. Such an array is sometimes called a hash or dictionary ; in the ruby world, we preferthe term hash . A hash can be constructed by quoting pairs of items within curly braces ( ). You use a keyto find something in a hash, much as you use an index to find something in an array.

    r uby>

    r uby>

    Page 16 :

  • 7/31/2019 Ruby User's Guide

    17/68

    y User's Guide - Arrays 3 3

    eHome Workstation 2006/10/29 07:45

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    Page 17 :

  • 7/31/2019 Ruby User's Guide

    18/68

    y User's Guide - Back to the simple examples 1 5

    eHome Workstation 2006/10/29 07:45

    Back to the simple examples

    Now let's take apart the code of some of our previous example programs.

    The following appeared in thesimple exampleschapter.

    d e f f a c t ( n )i f n = = 0

    1e l s e

    n * f a c t ( n - 1 )e n d

    e n dp u t s f a c t ( ARGV[ 0 ] . t o _ i )

    Because this is the first explanation, we examine each line individually.

    d e f f a c t ( n )

    In the first line, is a statement to define a function (or, more precisely, a method ; we'll talk more aboutwhat a method is in a later chapter). Here, it specifies that the function takes a single argument,

    referred to as .

    i f n = = 0

    The is for checking a condition. When the condition holds, the next bit of code is evaluated; otherwisewhatever follows the is evaluated.

    1

    The value of is 1 if the condition holds.

    e l s e

    If the condition does not hold, the code from here to is evaluated.

    n * f a c t ( n - 1 )

    If the condition is not satisfied, the value of is the result of times .

    e n d

    The first closes the statement.

    Page 18 :

  • 7/31/2019 Ruby User's Guide

    19/68

    y User's Guide - Back to the simple examples 2 5

    eHome Workstation 2006/10/29 07:45

    e n d

    The second closes the statement.

    p u t s f a c t ( ARGV[ 0 ] . t o _ i )

    This invokes our function using a value specified from the command line, and prints the result.

    is an array which contains command line arguments. The members of are strings, so we mustconvert this into a integral number by . Ruby does not convert strings into integers automatically likeperl does.

    What would happen if we fed this program a negative number? Do you see the problem? Can you fix it?

    Next we examine the puzzle program from the chapter onstrings. As this is somewhat longer, we number

    the lines for reference.

    0 1 wo r d s = [ ' f o o b a r ' , ' b a z ' , ' q u u x ' ]0 2 s e c r e t = wo r d s [ r a n d ( 3 ) ]0 30 4 p r i n t " g u e s s ? "0 5 wh i l e g u e s s = ST DI N. g e t s0 6 g u e s s . c h o p !0 7 i f g u e s s = = s e c r e t0 8 p u t s " Yo u wi n ! "0 9 b r e a k1 0 e l s e1 1 p u t s " So r r y , y o u l o s e . "1 2 e n d1 3 p r i n t " g u e s s ? "1 4 e n d1 5 p u t s " t h e wo r d i s " , s e c r e t , " . "

    In this program, a new control structure, , is used. The code between and its correspondingwill execute repeatedly as long as some specified condition remains true. In this case,is both an active statement (collecting a line of user input and storing it as ), and a condition (if thereis no input, , which repesents the value of the whole expression, has a nil value,causing to stop looping).

    is the standard input object. Usually, does the same thing as .

    in line 2 returns a random number in the range 0 to 2. This random number is used to extract oneof the members of the array .

    In line 5 we read one line from standard input by the method . If EOF (end of file) occurs whilegetting the line, returns . So the code associated with this will repeat until it sees^D (try ^Z or F6 under DOS/Windows), signifying the end of input.

    in line 6 deletes the last character from ; in this case it will always be a newline

    Page 19 :

  • 7/31/2019 Ruby User's Guide

    20/68

    y User's Guide - Back to the simple examples 3 5

    eHome Workstation 2006/10/29 07:45

    character, includes that character to reflect the user's Return keystroke, but we're not interested in it.

    In line 15 we print the secret word. We have written this as a ( tring) statement with twoarguments, which are printed one after the other; but it would have been equally effective to do it with asingle argument, writing as to make it clear that it is a variable to be evaluated, not aliteral word to be printed:

    p u t s " t h e wo r d i s # { s e c r e t } . "

    Many programmers feel this is a cleaner way to express output; it builds a single string and presents it as asingle argument to .

    Also, we are by now used to the idea of using for standard script output, but this script usesinstead, in lines 4 and 13. They are not quite the same thing. outputs exactly what it is given;also ensures that the output line ends. Using in lines 4 and 13 leaves the cursor next to what was justprinted, rather than moving it to the beginning of the next line. This creates a recognizable prompt for userinput. In general, the four output calls below are equivalent:

    # n e wl i n e i s i mp l i c i t l y a d d e d b y p u t s i f t h e r e i s n ' t o n ea l r e a d y :p u t s " Da r wi n ' s wi f e , Es me r e l d a , d i e d i n a f i t o f p e n g u i n s . "

    # n e wl i n e mu s t b e e x p l i c i t l y g i v e n t o t h e p r i n t c o mma n d :p r i n t " Da r wi n ' s wi f e , Es me r e l d a , d i e d i n a f i t o fp e n g u i n s . \ n "

    # y o u c a n c o n c a t e n a t e o u t p u t wi t h + :p r i n t ' Da r wi n ' s wi f e , Es me r e l d a , d i e d i n a f i t o fp e n g u i n s . ' + " \ n "

    # o r c o n c a t e n a t e b y s u p p l y i n g mo r e t h a n o n e s t r i n g :p r i n t ' Da r wi n ' s wi f e , Es me r e l d a , d i e d i n a f i t o f p e n g u i n s . ' ," \ n "

    One possible gotcha: sometimes a text window is programmed to buffer output for the sake of speed,collecting individual characters and displaying them only when it is given a newline character. So if theguessing game script misbehaves by not showing the prompt lines until after the user supplies a guess,

    buffering is the likely culprit. To make sure this doesn't happen, you can the output as soon as youhave printed the prompt. It tells the standard output device (an object named ), "don't wait; displaywhat you have in your buffer right now."

    0 4 p r i n t " g u e s s ? " ; ST DOUT . f l u s h. . .

    1 3 p r i n t " g u e s s ? " ; ST DOUT . f l u s h

    And in fact, we were more careful with this in the next script.

    Finally we examine this program from the chapter onregular expressions.

    Page 20 :

  • 7/31/2019 Ruby User's Guide

    21/68

    y User's Guide - Back to the simple examples 4 5

    eHome Workstation 2006/10/29 07:45

    0 1 s t = " \ 0 3 3 [ 7 m"0 2 e n = " \ 0 3 3 [ m"0 30 4 p u t s " E n t e r a n e mp t y s t r i n g a t a n y t i me t o e x i t . "0 50 6 wh i l e t r u e0 7 p r i n t " s t r > " ; ST DOUT . f l u s h ; s t r = g e t s . c h o p

    0 8 b r e a k i f s t r . e mp t y ?0 9 p r i n t " p a t > " ; ST DOUT . f l u s h ; p a t = g e t s . c h o p1 0 b r e a k i f p a t . e mp t y ?1 1 r e = Re g e x p . n e w( p a t )1 2 p u t s s t r . g s u b ( r e , " # { s t } \ \ { e n } " )1 3 e n d

    In line 6, the condition for is hardwired to , so it forms what looks like an infinite loop.However we put statements in the 8th and 10th lines to escape the loop. These two s are alsoan example of " modifiers." An modifier executes the statement on its left hand side if and only if the

    specified condition is satisfied. This construction is unusual in that it operates logically from right to left, butit is provided because for many people it mimics a similar pattern in natural speech. It also has the advantageof brevity, as it needs no statement to tell the interpreter how much of the following code is supposed tobe conditional. An modifier is conventionally used in situations where a statement and condition are shortenough to fit comfortably together on one script line.

    Note the difference in the user interface compared to the string-guessing script. This one lets the user quit byhitting the Return key on an empty line. We testing for emptiness of the input st ring, not for its nonexistence.

    In lines 7 and 9 we have a "non-destructive" chop; again, we're getting rid of the unwanted newline characterwe always get from . Add the explanation point, and we have a "destructive" chop. What's thedifference? In ruby, we conventionally attach ' ' or ' ' to the end of certain method names. The exclamationpoint ( , sometimes pronounced aloud as "bang!") indicates something potentially destructive, that is to say,something that can change the value of what it touches. affects a string directly, but gives you achopped copy without damaging the original. Here is an illustration of the difference.

    r u b y >" f o r t h "

    r u b y >" f o r t "

    r u b y >" f o r "

    r u b y >" f o r t "

    You'll also sometimes see and used. These are more selective: the end of a string gets bit off only if it happens to be a newline. So for example, does nothing. If you need a trick toremember the difference, think of a person or animal tasting something before deciding to take a bite, as

    opposed to an axe chopping indiscriminately.

    The other method naming convention appears in lines 8 and 10. A question mark (, sometimes pronouncedaloud as "huh?") indicates a "predicate" method, one that can return either or .

    Page 21 :

  • 7/31/2019 Ruby User's Guide

    22/68

    y User's Guide - Back to the simple examples 5 5

    eHome Workstation 2006/10/29 07:45

    Line 11 creates a regular expression object out of the string supplied by the user. The real work is finallydone in line 12, which uses to lobally stitute each match of that expression with itself, butsurrounded by ansi markups; also the same line outputs the results.

    We could have broken up line 12 into separate lines like this:

    h i g h l i g h t e d = s t r . g s u b ( r e , " # { s t } \ \ { e n } " )p u t s h i g h l i g h t e d

    or in "destructive" style:

    s t r . g s u b ! ( r e , " # { s t } \ \ & # { e n } " )p u t s s t r

    Look again at the last part of line 12. and were defined in lines 1-2 as the ANSI sequences that maketext color-inverted and normal, respectively. In line 12 they are enclosed in to ensure that they areactually interpreted as such (and we do not see the variable names printed instead). Between these we see

    . This is a little tricky. Since the replacement string is in double quotes, the pair of backslashes will beinterpreted as a single backslash; what actually sees will be , and that happens to be a special codethat refers to whatever matched the pattern in the first place. So the new string, when displayed, looks justlike the old one, except that the parts that matched the given pattern are highlighted in inverse video.

    Page 22 :

  • 7/31/2019 Ruby User's Guide

    23/68

    y User's Guide - Control structures 1 4

    eHome Workstation 2006/10/29 07:45

    Control structures

    Page 23 :

  • 7/31/2019 Ruby User's Guide

    24/68

    y User's Guide - Control structures 2 4

    eHome Workstation 2006/10/29 07:45

    This chapter explores more of ruby's control structures.

    We use the statement to test a sequence of conditions. This is superficially similar to in C andJava but is considerably more powerful, as we shall see.

    r u b y >r u b y >

    |||||

    6 . . 1 0

    is an expression which means the range between 2 and 5, inclusive. The following expression testswhether the value of falls within that range:

    ( 2 . . 5 ) = = = i

    internally uses the relationship operator to check for several conditions at a time. In keeping withruby's object oriented nature, is interpreted suitably for the object that appeared in the condition.For example, the following code tests string equality in the first , and regular expression matching inthe second .

    r u b y >|||||

    i n c l u d e s / d e f /

    Ruby provides convenient ways to construct loops, although you will find in the next chapter that learninghow to use iterators will make it unnecessary to write explicit loops very often.

    A is a repeated . We used it in our word-guessing puzzle and in the regular expression programs(see the previous chapter); there, it took the form surrounding a block of codeto be repeated whilecondition was true. But and can as easily be applied to individual statements:

    r u b y >

    r u b y >

    Page 24 :

  • 7/31/2019 Ruby User's Guide

    25/68

    y User's Guide - Control structures 3 4

    eHome Workstation 2006/10/29 07:45

    I t ' s z e r o .

    r u b y >

    r u b y >123

    Sometimes you want to negate a test condition. An is a negated , and an is a negated. We'll leave it up to you to experiment with these.

    There are four ways to interrupt the progress of a loop from inside. First, means, as in C, to escapefrom the loop entirely. Second, skips to the beginning of the next iteration of the loop (correspondingto C's ). Third, ruby has , which restarts the current iteration. The following is C codeillustrating the meanings of , and :

    wh i l e ( c o n d i t i o n ) {l a b e l _ r e d o :

    g o t o l a b e l _ n e x t ; / * r u b y ' s " n e x t " * /g o t o l a b e l _ b r e a k ; / * r u b y ' s " b r e a k " * /g o t o l a b e l _ r e d o ; / * r u b y ' s " r e d o " * /. . .. . .

    l a b e l _ n e x t :}l a b e l _ b r e a k :. . .

    The fourth way to get out of a loop from the inside is . An evaluation of causes escape notonly from a loop but from the method that contains the loop. If an argument is given, it will be returned fromthe method call, otherwise is returned.

    C programmers will be wondering by now how to make a "for" loop. Ruby's can serve the same

    purpose, but adds some flexibility. The loop below runs once for each element in acollection (array, hash,numeric sequence, etc.), but doesn't make the programmer think about indices:

    f o r e l t i n c o l l e c t i o n# . . . h e r e , e l t r e f e r s t o a n e l e me n t o f t h e c o l l e c t i o n

    e n d

    The collection can be a range of values (this is what most people mean when they talk about a for loop):

    r u b y >||

    45

    Page 25 :

  • 7/31/2019 Ruby User's Guide

    26/68

    y User's Guide - Control structures 4 4

    eHome Workstation 2006/10/29 07:45

    6

    In this example we step through some array elements:

    r u b y >||

    1 0 0 ( F i x n u m)- 9 . 6 ( F l o a t )p i c k l e ( S t r i n g )

    But we're getting ahead of ourselves. is really another way of writing , which, it so happens, is ourfirst example of an iterator. The following two forms are equivalent:

    # I f y o u ' r e u s e d t o C o r J a v a , y o u mi g h t p r e f e r t h i s .f o r e l e me n t i n c o l l e c t i o n

    . . .e n d

    # A Sma l l t a l k p r o g r a mme r mi g h t p r e f e r t h i s .c o l l e c t i o n . e a c h { | e l e me n t |

    . . .}

    Iterators can often be substituted for conventional loops, and once you get used to them, they are generallyeasier to deal with. So let's move on and learn more about them.

    Page 26 :

  • 7/31/2019 Ruby User's Guide

    27/68

    y User's Guide - Iterators 1 4

    eHome Workstation 2006/10/29 07:44

    Iterators

    Page 27 :

  • 7/31/2019 Ruby User's Guide

    28/68

    y User's Guide - Iterators 2 4

    eHome Workstation 2006/10/29 07:44

    Iterators are not an original concept with ruby. They are in common use in object-oriented languages. Theyare also used in Lisp, though there they are not called iterators. However the concepet of iterator is anunfamiliar one for many so it should be explained in more detail.

    The verb iterate means to do the same thing many times, you know, so an iterator is something that does thesame thing many times.

    When we write code, we need loops in various situations. In C, we code them using or . Forexample,

    c h a r * s t r ;f o r ( s t r = " a b c d e f g " ; * s t r ! = ' \ 0 ' ; s t r + + ) {

    / * p r o c e s s a c h a r a c t e r h e r e * /}

    C's syntax provides an abstraction to help with the creation of a loop, but the test of against a null character requires the programmer to know details about the internal structure of a string. Thismakes C feel like a low-level language. Higher level languages are marked by their more flexible support foriteration. Consider the following shell script:

    # ! / b i n / s h

    f o r i i n * . [ c h ] ; d o# . . . h e r e wo u l d b e s o me t h i n g t o d o f o r e a c h f i l e

    d o n e

    All the C source and header files in the current directory are processed, and the command shell handles thedetails of picking up and substituting file names one by one. I think this is working at a higher level than C,don't you?

    But there is more to consider: while it is fine for a language to provide iterators for built-in data types, it is adisappointment if we must go back to writing low level loops to iterate over our own data types. In OOP,users often define one data type after another, so this could be a serious problem.

    So every OOP language includes some facilities for iteration. Some languages provide a special class for thispurpose; ruby allows us to define iterators directly.

    Ruby's type has some useful iterators:

    r u b y >< a > < b > < c >

    is an iterator for each character in the string. Each character is substituted into the local variable. This can be translated into something that looks a lot like C code ...

    r u b y >

    r u b y >

    Page 28 :

  • 7/31/2019 Ruby User's Guide

    29/68

    y User's Guide - Iterators 3 4

    eHome Workstation 2006/10/29 07:44

    ||

    < a > < b > < c >

    ... however, the iterator is both conceptually simpler and more likely to continue to work even if the class happens to be radically modified in the future. One benefit of iterators is that they tend tobe robust in the face of such changes; indeed that is a characteristic of good code in general. (Yes, have

    patience, we're about to talk about whatclasses are, too.)

    Another iterator of is .

    r u b y >abc

    The tasks that would take most of the programming effort in C (finding line delimiters, generatingsubstrings, etc.) are easily tackled using iterators.

    The statement appearing in the previous chapter does iteration by way of an iterator. 'sworks the same as , so let's rewrite the above example with :

    r u b y >|

    |abc

    We can use a control structure in conjunction with an iterated loop, and it will retry the loop from thebeginning.

    r u b y >

    r u b y >|||||||

    0 1 20 1 2 3 4

    Replacing in the above example with causes just the current iteration of the loop to be redone,

    Page 29 :

  • 7/31/2019 Ruby User's Guide

    30/68

    y User's Guide - Iterators 4 4

    eHome Workstation 2006/10/29 07:44

    with this output:

    0 1 22 3 4

    occurs sometimes in a definition of an iterator. moves control to the block of code that ispassed to the iterator (this will be explored in more detail in the chapter aboutprocedure objects). Thefollowing example defines an iterator , which repeats a block of code the number of times specifiedin an argument.

    r u b y >|||||

    r u b y >f o of o of o o

    With , one can define an iterator which works something like ruby's standard .

    r u b y >||||

    r u b y >0 1 2 n i l

    Do you understand what an iterator is? There are a few restrictions, but you can write your original iterators;

    and in fact, whenever you define a new data type, it is often convenient to define suitable iterators to go withit. In this sense, the above examples are not terribly useful. We can talk about practical iterators after wehave a better understanding of what classes are.

    Page 30 :

  • 7/31/2019 Ruby User's Guide

    31/68

    y User's Guide - Object-oriented thinking 1 2

    eHome Workstation 2006/10/29 07:43

    Object-oriented thinking

    Object oriented is a catchy phrase. To call anything object oriented can make you sound pretty smart. Rubyclaims to be an object oriented scripting language; but what exactly does "object oriented" mean?

    There have been a variety of answers to that question, all of which probably boil down to about the samething. Rather than sum it too quickly, let's think for a moment about the traditional programming paradigm.

    Traditionally, a programming problem is attacked by coming up with some kinds of data representations , and procedures that operate on that data. Under this model, data is inert, passive, and helpless; it sits at thecomplete mercy of a large procedural body, which is active, logical, and all-powerful.

    The problem with this approach is that programs are written by programmers, who are only human and canonly keep so much detail clear in their heads at any one time. As a project gets larger, its procedural coregrows to the point where it is difficult to remember how the whole thing works. Minor lapses of thinking andtypographical errors become more likely to result in well-concealed bugs. Complex and unintendedinteractions begin to emerge within the procedural core, and maintaining it becomes like trying to carryaround an angry squid without letting any tentacles touch your face. There are guidelines for programmingthat can help to minimize and localize bugs within this traditional paradigm, but there is a better solution thatinvolves fundamentally changing the way we work.

    What object-oriented programming does is to let us delegate most of the mundane and repetitive logicalwork to the data itself ; it changes our concept of data from passive to active . Put another way,

    We stop treating each piece of data as a box with an open lid that lets us reach in and throw thingsaround.We start treating each piece of data as a working machine with a closed lid and a few well-markedswitches and dials.

    What is described above as a "machine" may be very simple or complex on the inside; we can't tell from theoutside, and we don't allow ourselves to open the machine up (except when we are absolutely sure somethingis wrong with its design), so we are required to do things like flip the switches and read the dials to interactwith the data. Once the machine is built, we don't want to have to think about how it operates.

    You might think we are just making more work for ourselves, but this approach tends to do a nice job of preventing all kinds of things from going wrong.

    Let's start with a example that is too simple to be of practical value, but should illustrate at least part of theconcept. Your car has a tripmeter. Its job is to keep track of the distance the car has travelled since the lasttime its reset button was pushed. How would we model this in a programming language? In C, the tripmeterwould just be a numeric variable, possibly of type . The program would manipulate that variable byincreasing its value in small increments, with occasional resets to zero when appropriate. What's wrong withthat? A bug in the program could assign a bogus value to the variable, for any number of unexpectedreasons. Anyone who has programmed in C knows what it is like to spend hours or days tracking down sucha bug whose cause seems absurdly simple once it has been found. (The moment of finding the bug iscommonly indicated by the sound of a loud slap to the forehead.)

    The same problem would be attacked from a much different angle in an object-oriented context. The first

    Page 31 :

  • 7/31/2019 Ruby User's Guide

    32/68

    y User's Guide - Object-oriented thinking 2 2

    eHome Workstation 2006/10/29 07:43

    thing a programmer asks when designing the tripmeter is not "which of the familiar data types comes closestto resembling this thing?" but "how exactly is this thing supposed to act?" The difference winds up being aprofound one. It is necessary to spend a little bit of time deciding exactly what an odometer is for, and howthe outside world expects to interact with it. We decide to build a little machine with controls that allow us toincrement it, reset it, read its value, and nothing else.

    We don't provide a way for a tripmeter to be assigned arbitrary values; why? because we all know tripmetersdon't work that way. There are only a few things you should be able to do with a tripmeter, and those are all

    we allow. Thus, if something else in the program mistakenly tries to place some other value (say, the targettemperature of the vehicle's climate control) into the tripmeter, there is an immediate indication of what wentwrong. We are told when running the program (or possibly while compiling, depending on the nature of thelanguage) thatwe are not allowed to assign arbitrary values to Tripmeter objects . The message might not beexactly that clear, but it will be reasonably close to that. It doesn't prevent the error, does it? But it quicklypoints us in the direction of the cause. This is only one of several ways in which OO programming can savea lot of wasted time.

    We commonly take one step of abstraction above this, because it turns out to be as easy to build a factorythat makes machines as it is to make an individual machine. We aren't likely to build a single tripmeterdirectly; rather, we arrange for any number of tripmeters to be built from a single pattern. The pattern (or if you like, the tripmeter factory) corresponds to what we call aclass , and an individual tripmeter generatedfrom the pattern (or made by the factory) corresponds to anobject . Most OO languages require a class to bedefined before we can have a new kind of object, but ruby does not.

    It's worth noting here that the use of an OO language will notenforce proper OO design. Indeed it is possiblein any language to write code that is unclear, sloppy, ill-conceived, buggy, and wobbly all over. What rubydoes for you (as opposed, especially, to C++) is to make the practice of OO programming feel naturalenough that even when you are working on a small scale you don't feel a necessity to resort to ugly code to

    save effort. We will be discussing the ways in which ruby accomplishes that admirable goal as this guideprogresses; the next topic will be the "switches and dials" (object methods) and from there we'll move on tothe "factories" (classes). Are you still with us?

    Page 32 :

  • 7/31/2019 Ruby User's Guide

    33/68

    y User's Guide - Methods 1 2

    eHome Workstation 2006/10/29 07:44

    Methods

    What is a method? In OO programming, we don't think of operating on data directly from outside an object;rather, objects have some understanding of how to operate on themselves (when asked nicely to do so). Youmight say we pass messages to an object, and those messages will generally elicit some kind of an action ormeaningful reply. This ought to happen without our necessarily knowing or caring how the object reallyworks inside. The tasks we are allowed to ask an object to perform (or equivalently, the messages itunderstands) are that object's methods .

    In ruby, we invoke a method of an object with dot notation (just as in C++ or Java). The object being talkedto is named to the left of the dot.

    r u b y >

    Intuitively, this string object is being asked how long it is . Technically, we are invoking the methodof the object .

    Other objects may have a slightly different interpretation of , or none at all. Decisions about how torespond to a message are made on the fly, during program execution, and the action taken may changedepending on what a variable refers to.

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    What we mean by length can vary depending on what object we are talking about. The first time we askfor its length in the above example, it refers to a simple string, and there can only be one sensible answer.The second time, refers to an array, and we might reasonably think of its length as either 2, 5, or 10;but the most generally applicable answer is of course 2 (the other kinds of length can be figured out if wished).

    r u b y >

    r u b y >

    The thing to notice here is that an array knows something about what it means to be an array . Pieces of datain ruby carry such knowledge with them, so that the demands made on them can automatically be satisfied inthe various appropriate ways. This relieves the programmer from the burden of memorizing a great many

    Page 33 :

  • 7/31/2019 Ruby User's Guide

    34/68

    y User's Guide - Methods 2 2

    eHome Workstation 2006/10/29 07:44

    specific function names, because a relatively small number of method names, corresponding to concepts thatwe know how to express in natural language, can be applied to different kinds of data and the results will bewhat we expect. This feature of OO programming languages (which, IMHO, Java has done a poor job of exploiting) is called polymorphism .

    When an object receives a message that it does not understand, an error is "raised":

    r u b y >

    r u b y >

    So it is necessary to know what methods are acceptable to an object, though we need not know how themethods are processed.

    If arguments are given to a method, they are generally surrounded by parentheses,

    o b j e c t . me t h o d ( a r g 1 , a r g 2 )

    but they can be omitted if doing so does not cause ambiguity.

    o b j e c t . me t h o d a r g 1 , a r g 2

    There is a special variable in ruby; it refers to whatever object calls a method. This happens so oftenthat for convenience the " " may be omitted from method calls from an object to itself:

    s e l f . me t h o d _ n a me ( a r g s . . . )

    is the same as

    me t h o d _ n a me ( a r g s . . . )

    What we would think of traditionally as a function call is just this abbreviated way of writing methodinvocations by . This makes ruby what is called a pure object oriented language. Still, functionalmethods behave quite similarly to the functions in other programming languages for the benefit of those whodo not grok how function calls are really object methods in ruby. We can speak of functions as if they were

    not really object methods if we want to.

    Page 34 :

  • 7/31/2019 Ruby User's Guide

    35/68

    y User's Guide - Classes 1 2

    eHome Workstation 2006/10/29 07:45

    Classes

    The real world is filled by objects, and we can classify them. For example, a very small child is likely to say"bow-wow" when seeing a dog, regardless of the breed; we naturally see the world in terms of thesecategories.

    In OO programming terminology, a category of objects like "dog" is called aclass , and some specific objectbelonging to a class is called an instance of that class.

    Generally, to make an object in ruby or any other OO language, first one defines the characteristics of aclass, then creates an instance. To illustrate the process, let 's first define a simple class.

    r u b y >

    ||||

    In ruby, a class definition is a region of code between the keywords and . A inside thisregion begins the definition of a method of the class, which as we discussed in the previous chapter,corresponds to some specific behavior for objects of that class.

    Now that we have defined a class, we can use it to make a dog:

    r u b y >

    We have made a new instance of the class , and have given it the name . The method of anyclass makes a new instance. Because is a according to our class definition, it has whateverproperties we decided a should have. Since our idea of -ness was very simple, there is just one trickwe can ask to do.

    r u b y >Bow Wow

    Making a new instance of a class is sometimes called instantiating that class. We need to have a dog beforewe can experience the pleasure of its conversation; we can't merely ask the Dogclass to bark for us.

    r u b y >

    It makes no more sense than trying toeat the concept of a sandwich .

    Page 35 :

  • 7/31/2019 Ruby User's Guide

    36/68

    y User's Guide - Classes 2 2

    eHome Workstation 2006/10/29 07:45

    On the other hand, if we want to hear the sound of a dog without getting emotionally attached, we can create(instantiate) an ephemeral, temporary dog, and coax a little noise out of it before it disappears.

    r u b y >Bow Wow

    "Wait," you say, "what's all this about the poor fellow disappearing afterwards?" It's true: if we don't botherto give it a name (as we did for ), ruby's automatic garbage collection decides it is an unwanted straydog, and mercilessly disposes of it. Really it's okay, you know, because we can make all the dogs we want.

    Page 36 :

  • 7/31/2019 Ruby User's Guide

    37/68

    y User's Guide - Inheritance 1 2

    eHome Workstation 2006/10/29 07:44

    Inheritance

    Our classification of objects in everyday life is naturally hierarchical. We know thatall cats are mammals ,and all mammals are animals . Smaller classes inherit characteristics from the larger classes to which theybelong. If all mammals breathe, then all cats breathe.

    We can express this concept in ruby:

    r u b y >||||

    r u b y >||||

    Though we didn't specify how a should breathe, every cat will inherit that behavior from theclass since was defined as a subclass of . (In OO terminology, the smaller class is asubclass andthe larger class is a superclass .) Hence from a programmer's standpoint, cats get the ability to breathe forfree; after we add a method, our cats can both breathe and speak.

    r u b y >

    r u b y >i n h a l e a n d e x h a l e

    r u b y >

    M e o w

    There will be situations where certain properties of the superclass should not be inherited by a particularsubclass. Though birds generally know how to fly, penguins are a flightless subclass of birds.

    r u b y >||

    |||||

    Page 37 :

  • 7/31/2019 Ruby User's Guide

    38/68

    y User's Guide - Inheritance 2 2

    eHome Workstation 2006/10/29 07:44

    r u b y >||||

    Rather than exhaustively define every characteristic of every new class, we need only to append or toredefine the differences between each subclass and its superclass. This use of inheritance is sometimes calleddifferential programming . It is one of the benefits of object-oriented programming.

    Page 38 :

  • 7/31/2019 Ruby User's Guide

    39/68

    y User's Guide - Redefinition of methods 1 3

    eHome Workstation 2006/10/29 07:43

    Redefinition of methods

    Page 39 :

  • 7/31/2019 Ruby User's Guide

    40/68

    y User's Guide - Redefinition of methods 2 3

    eHome Workstation 2006/10/29 07:43

    In a subclass, we can change the behavior of the instances by redefining superclass methods.

    r u b y >|||||||||||

    r u b y >I ' m a p e r s o n .

    r u b y >||||

    r u b y >I ' m a s t u d e n t .

    Suppose we would rather enhance the superclass's method than entirely replace it. For this we canuse .

    r u b y >|||||

    r u b y >I ' m a h u ma n .I ' m a s t u d e n t t o o .

    lets us pass arguments to the original method. It is sometimes said that there are two kinds of people...

    r u b y >||

    Page 40 :

  • 7/31/2019 Ruby User's Guide

    41/68

    y User's Guide - Redefinition of methods 3 3

    eHome Workstation 2006/10/29 07:43

    ||

    r u b y >Re d u c e d f a r e .

    r u b y >||||

    r u b y >No r ma l f a r e .

    Page 41 :

  • 7/31/2019 Ruby User's Guide

    42/68

    y User's Guide - Access control 1 2

    eHome Workstation 2006/10/29 07:45

    Access control

    Earlier, we said that ruby has no functions, only methods. However there is more than one kind of method.In this chapter we introduceaccess controls .

    Consider what happens when we define a method in the "top level", not inside a class definition. We canthink of such a method as analogous to a function in a more traditional language like C.

    r u b y >||

    r u b y >

    Our new method would appear not to belong to any class, but in fact ruby gives it to the class,which is a superclass of every other class. As a result, any object should now be able to use that method.That turns out to be true, but there's a small catch: it is a private method of every class. We'll discuss some of what this means below, but one consequence is that it may be invoked only in function style, as here:

    r u b y >|

    |||

    n i lr u b y >

    1 0 0 0 0

    We are not allowed to explicitly apply the method to an object:

    r u b y >

    This rather cleverly preserves ruby's pure-OO nature (functions are still object methods, but the receiver isimplicitly) while providing functions that can be written just as in a more traditional language.

    A common mental discipline in OO programming, which we have hinted at in an earlier chapter, concernsthe separation of specification and implementation , or what tasks an object is supposed to accomplish and

    how it actually accomplishes them. The internal workings of an object should be kept generally hidden fromits users; they should only care about what goes in and what comes out, and trust the object to know what itis doing internally. As such it is often helpful for classes to have methods that the outside world does not see,but which are used internally (and can be improved by the programmer whenever desired, without changingthe way users see objects of that class). In the trivial example below, think of as the invisible inner

    Page 42 :

  • 7/31/2019 Ruby User's Guide

    43/68

    y User's Guide - Access control 2 2

    eHome Workstation 2006/10/29 07:45

    workings of the class.

    r u b y >|||||

    |||

    r u b y >

    r u b y >

    r u b y >

    6 t i me s t wo i s 1 2 .

    We might have expected to return 12, but instead we learn that is inaccessiblewhen we are acting as a user of a object. Only other methods, such as , are allowedto use . We are required to go through the public interface, which consists of themethod. The programmer who is in charge of this class can change freely (here, perhaps bychanging to , assuming for the sake of argument that it improved performance) without affectinghow the user interacts with objects. This example is of course much too simple to be useful; the

    benefits of access controls become more clear only when we begin to create more complicated andinteresting classes.

    Page 43 :

  • 7/31/2019 Ruby User's Guide

    44/68

    y User's Guide - Singleton methods 1 1

    eHome Workstation 2006/10/29 07:42

    Singleton methods

    The behavior of an instance is determined by its class, but there may be times we know that a particularinstance should have special behavior. In most languages, we must go to the trouble of defining anotherclass, which would then only be instantiated once. In ruby we can give any object its own methods.

    r uby>||||

    r uby>

    r uby>

    r uby>||

    r uby>

    r uby>

    In this example, and belong to same class, but has been given a redefinedmethod and so they behave differently. A method given only to a single object is called asingleton method .

    Singleton methods are often used for elements of a graphic user interface (GUI), where different actionsneed to be taken when different buttons are pressed.

    Singleton methods are not unique to ruby, as they appear in CLOS, Dylan, etc. Also, some languages, forexample, Self and NewtonScript, have singleton methods only. These are sometimes called prototype-based languages.

    Page 44 :

  • 7/31/2019 Ruby User's Guide

    45/68

    y User's Guide - Modules 1 1

    eHome Workstation 2006/10/29 07:43

    Modules

    Modules in ruby are similar to classes, except:

    A module can have no instances.A module can have no subclasses.A module is defined by .

    Actually... the Module class of module is the superclass of the Class class of class. Got that? No? Let's moveon.

    There are two typical uses of modules. One is to collect related methods and constants in a central location.The module in ruby's standard library plays such a role:

    r uby>

    r uby>

    The operator tells the ruby interpreter which module it should consult for the value of a constant(conceivably, some module besides might mean something else by ). If we want to refer to themethods or constants of a module directly without using , we can that module:

    r uby>

    r uby>

    r uby>

    Another use of modules is called mixin . Some OO programming langages, including C++, allow multiple inheritance , that is, inheritance from more than one superclass. A real-world example of multiple inheritanceis an alarm clock; you can think of alarm clocks as belonging to the class of clocks and also the class of things with buzzers .

    Ruby purposely does not implement true multiple inheritance, but the mixin technique is a good alternative.Remember that modules cannot be instantiated or subclassed; but if we a module in a classdefinition, its methods are effectively appended, or "mixed in", to the class.

    Mixin can be thought of as a way of asking for whatever particular properties we want to have. For example,if a class has a working method, mixing in the standard library's module gives us

    and methods for free.This use of modules gives us the basic functionality of multiple inheritance but allows us to represent classrelationships with a simple tree structure, and so simplifies the language implementation considerably (asimilar choice was made by the designers of Java).

    Page 45 :

  • 7/31/2019 Ruby User's Guide

    46/68

    y User's Guide - Procedure objects 1 2

    eHome Workstation 2006/10/29 07:43

    Procedure objects

    It is often desirable to be able to specify responses to unexpected events. As it turns out, this is most easilydone if we can pass blocks of code as arguments to other methods, which means we want to be able to treatcode as if it were data.

    A new procedure object is formed using :

    r uby>||

    Now what refers to is an object, and like most objects, it has behavior that can be invoked.Specifically, we can ask it to execute, via its method:

    r uby>QUUXQUUXQUUX! ! !

    So, after all that, can be used as a method argument? Sure.

    r uby>||||

    r uby>About t o c al l a pr oc edur e. . .QUUXQUUXQUUX! ! !

    Ther e: f i ni s hed.

    The method lets us assign the response of our choice to any system signal.

    r uby>

    r uby>

    Normally pressing^C makes the interpreter quit. Now a message is printed and the interpreter continuesrunning, so you don't lose the work you were doing. (You're not trapped in the interpreter forever; you canstill exit by typing .)

    Page 46 :

  • 7/31/2019 Ruby User's Guide

    47/68

  • 7/31/2019 Ruby User's Guide

    48/68

    y User's Guide - Variables 1 1

    eHome Workstation 2006/10/29 07:41

    Variables

    Ruby has three kinds of variables, one kind of constant and exactly two pseudo-variables. The variables andthe constants have no type. While untyped variables have some drawbacks, they have many more advantagesand fit well with ruby'squick and easy philosophy.

    Variables must be declared in most languages in order to specify their type, modifiability (i.e., whether theyare constants), and scope; since type is not an issue, and the rest is evident from the variable name as you areabout to see, we do not need variable declarations in ruby.

    The first character of an identifier categorizes it at a glance:

    global variable

    instance variableor local variable

    constant

    The only exceptions to the above are ruby's pseudo-variables: , which always refers to the currentlyexecuting object, and , which is the meaningless value assigned to uninitialized variables. Both arenamed as if they are local variables, but is a global variable maintained by the interpreter, and isreally a constant. As these are the only two exceptions, they don't confuse things too much.

    You man not assign values to or . , as a value of , refers to the top-level object:

    r u b y >

    r u b y >

    Page 48 :

  • 7/31/2019 Ruby User's Guide

    49/68

    y User's Guide - Global variables 1 2

    eHome Workstation 2006/10/29 07:44

    Global variables

    A global variable has a name beginning with . It can be referred to from anywhere in a program. Beforeinitialization, a global variable has the special value .

    r uby>

    r uby>

    r uby>

    Global variables should be used sparingly. They are dangerous because they can be written to fromanywhere. Overuse of globals can make isolating bugs difficult; it also tends to indicate that the design of aprogram has not been carefully thought out. Whenever you do find it necessary to use a global variable, besure to give it a descriptive name that is unlikely to be inadvertently used for something else later (calling itsomething like as above is probably a bad idea).

    One nice feature of a global variable is that it can be traced; you can specify a procedure which is invokedwhenever the value of the variable is changed.

    r uby>

    r uby>$x i s now 5

    When a global variable has been rigged to work as a trigger to invoke a procedure whenever changed, wesometimes call it anactive variable . For instance, it might be useful for keeping a GUI display up to date.

    There is a collection of special variables whose names consist of a dollar sign () followed by a singlecharacter. For example, contains the process id of the ruby interpreter, and is read-only. Here are themajor system variables:

    latest error message

    location of error

    string last read by

    line number last read by interpreter

    string last matched by regexp

    the last regexp match, as an array of subexpressions n the nth subexpression in the last match (same as n )

    case-insensitivity flag

    input record separator

    Page 49 :

  • 7/31/2019 Ruby User's Guide

    50/68

    y User's Guide - Global variables 2 2

    eHome Workstation 2006/10/29 07:44

    output record separator

    the name of the ruby script file

    the command line arguments

    interpreter's process ID

    exit status of last executed child process

    In the above, and have local scope. Their names suggest they should be global, but they are muchmore useful this way, and there are historical reasons for using these names.

    Page 50 :

  • 7/31/2019 Ruby User's Guide

    51/68

    y User's Guide - Instance variables 1 1

    eHome Workstation 2006/10/29 07:44

    Instance variables

    An instance variable has a name beginning with , and its scope is confined to whatever object refersto. Two different objects, even if they belong to the same class, are allowed to have different values for theirinstance variables. From outside the object, instance variables cannot be altered or even observed (i.e., ruby'sinstance variables are never public ) except by whatever methods are explicitly provided by the programmer.As with globals, instance variables have the value until they are initialized.

    Instance variables of ruby do not need declaration. This implies a flexible structure of objects. In fact, eachinstance variable is dynamically appended to an object when it is first referenced.

    r uby>|

    ||||||

    r uby>

    r uby>

    r uby>

    r uby>

    r uby>

    Notice above that does not report a value for until after the method is invoked.

    Page 51 :

  • 7/31/2019 Ruby User's Guide

    52/68

    y User's Guide - Local variables 1 3

    eHome Workstation 2006/10/29 07:44

    Local variables

    A local variable has a name starting with a lower case letter or an underscore character (). Local variablesdo not, like globals and instance variables, have the value before initialization:

    r u b y >

    r u b y >

    r u b y >

    The first assignment you make to a local variable acts something like a declaration. If you refer to anuninitialized local variable, the ruby interpreter cannot be sure whether you are referencing a bogus variableor calling a nonexistent method; hence the error message you see above.

    Generally, the scope of a local variable is one of

    ...

    ......

    ......

    the entire program (unless one of the above applies)

    In the next example, is an operator which checks whether an identifier is defined. It returns adescription of the identifier if it is defined, or otherwise. As you see, 's scope is local to the loop;when the loop exits, is undefined.

    r u b y >4 4

    r u b y >4 5

    Procedure objects that live in the same scope share whatever local variables also belong to that scope. Here,the local variable is shared by and the procedure objects and :

    r u b y >

    r u b y >

    r u b y >

    Page 52 :

  • 7/31/2019 Ruby User's Guide

    53/68

    y User's Guide - Local variables 2 3

    eHome Workstation 2006/10/29 07:44

    r u b y >

    r u b y >

    r u b y >

    Note that the " " at the beginning cannot be omitted; it ensures that the scope of will encompassand . Otherwise and would each end up with its own local variable , and calling would

    have resulted in an "undefined local variable or method" error. We could have said instead, but usingis a courtesy to others who will read your code later. It indicates fairly clearly that you are only

    establishing scope, because the value being assigned is not intended to be meaningful.

    A powerful feature of procedure objects follows from their ability to be passed as arguments: shared localvariables remain valid even when they are passed out of the original scope.

    r u b y >|||||

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Ruby is particularly smart about scope. It is evident in our example that the variable is beingshared between the and . But we can also manufacture multiple reader-writer pairs using

    as defined above; each pair shares a variable, and the pairs do not interfere with each other.

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    This kind of programming could be considered a perverse little object-oriented framework. The methodacts something like a class, with and serving as methods (except those aren't really the method

    Page 53 :

  • 7/31/2019 Ruby User's Guide

    54/68

    y User's Guide - Local variables 3 3

    eHome Workstation 2006/10/29 07:44

    names , which could vary with each box instance) and being the lone instance variable. Of course,using ruby's legitimate class framework leads to much more readable code.

    Page 54 :

  • 7/31/2019 Ruby User's Guide

    55/68

    y User's Guide - Class constants 1 2

    eHome Workstation 2006/10/29 07:45

    Class constants

    A constant has a name starting with an uppercase character. It should be assigned a value at most once. Inthe current implementation of ruby, reassignment of a constant generates a warning but not an error (thenon-ANSI version of eval.rb does not report the warning):

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Constants may be defined within classes, but unlike instance variables, they are accessible outside the class.

    r u b y >|||

    ||||

    r u b y >

    r u b y >

    r u b y >

    1 0 1 1 0 2 1 0 3

    Constants can also be defined in modules.

    r u b y >|||

    ||||

    Page 55 :

  • 7/31/2019 Ruby User's Guide

    56/68

    y User's Guide - Class constants 2 2

    eHome Workstation 2006/10/29 07:45

    r u b y >

    r u b y >

    r u b y >

    r u b y >1 0 1 1 0 2 1 0 3

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Page 56 :

  • 7/31/2019 Ruby User's Guide

    57/68

    y User's Guide - Exception processing: rescue 1 2

    eHome Workstation 2006/10/29 07:42

    Exception processing: rescue

    An executing program can run into unexpected problems. A file that it it wants to read might not exist; thedisk might be full when it wants to save some data; the user may provide it with some unsuitable kind of input.

    r u b y >

    A robust program will handle these situations sensibly and gracefully. Meeting that expectation can be anexasperating task. C programmers are expected to check the result of every system call that could possiblyfail, and immediately decide what is to be done:

    F I L E * f i l e = f o p e n ( " s o me _ f i l e " , " r " ) ;i f ( f i l e = = NUL L ) {

    f p r i n t f ( s t d e r r , " F i l e d o e s n ' t e x i s t . \ n " ) ;e x i t ( 1 ) ;

    }b y t e s _ r e a d = f r e a d ( b u f , 1 , b y t e s _ d e s i r e d , f i l e ) ;i f ( b y t e s _ r e a d ! = b y t e s _ d e s i r e d ) {

    / * d o mo r e e r r o r h a n d l i n g h e r e . . . * /

    }. . .

    This is such a tiresome practice that programmers can tend to grow careless and neglect it, and the result is aprogram that doesn't handle exceptions well. On the other hand, doing the job right can make programs hardto read, because there is so much error handling cluttering up the meaningful code.

    In ruby, as in many modern languages, we can handle exceptions for blocks of code in a compartmentalizedway, thus dealing with surprises effectively but not unduly burdening either the programmer or anyone elsetrying to read the code later. The block of code marked with executes until there is an exception,

    which causes control to be transferred to a block of error handling code, which is marked with . If noexception occurs, the code is not used. The following method returns the first line of a text file, or

    if there is an exception:

    d e f f i r s t _ l i n e ( f i l e n a me )b e g i n

    f i l e = o p e n ( " s o me _ f i l e " )i n f o = f i l e . g e t sf i l e . c l o s ei n f o # L a s t t h i n g e v a l u a t e d i s t h e r e t u r n v a l u e

    r e s c u en i l # Ca n ' t r e a d t h e f i l e ? t h e n d o n ' t r e t u r n a s t r i n g

    e n de n d

    Page 57 :

  • 7/31/2019 Ruby User's Guide

    58/68

    y User's Guide - Exception processing: rescue 2 2

    eHome Workstation 2006/10/29 07:42

    There will be times when we would like to be able to creatively work around a problem. Here, if the file wewant is unavailable, we try to use standard input instead:

    b e g i nf i l e = o p e n ( " s o me _ f i l e " )

    r e s c u ef i l e = ST DI N

    e n d

    b e g i n# . . . p r o c e s s t h e i n p u t . . .

    r e s c u e# . . . a n d d e a l wi t h a n y o t h e r e x c e p t i o n s h e r e .

    e n d

    can be used in the code to start the code over again. It lets us rewrite the previousexample a little more compactly:

    f n a me = " s o me _ f i l e "b e g i n

    f i l e = o p e n ( f n a me )# . . . p r o c e s s t h e i n p u t . . .

    r e s c u ef n a me = " ST DI N"r e t r y

    e n d

    However, there is a flaw here. A nonexistent file will make this code retry in an infinite loop. You need towatch out for such pitfalls when using for exception processing.

    Every ruby library raises an exception if any error occurs, and you can raise exceptions explicitly in yourcode too. To raise an exception, use . It takes one argument, which should be a string that describesthe exception. The argument is optional but should not be omitted. It can be accessed later via the specialglobal variable .

    r u b y >

    r u b y >||||

    An e r r o r o c c u r r e d : t e s t 2

    Page 58 :

  • 7/31/2019 Ruby User's Guide

    59/68

    y User's Guide - Exception processing: ensure 1 1

    eHome Workstation 2006/10/29 07:45

    Exception processing: ensure

    There may be cleanup work that is necessary when a method finishes its work. Perhaps an open file shouldbe closed, buffered data should be flushed, etc. If there were always only one exit point for each method, wecould confidently put our cleanup code in one place and know that it would be executed; however, a methodmight return from several places, or our intended cleanup code might be unexpectedly skipped because of anexception.

    b e g i nf i l e = o p e n ( " / t mp / s o me _ f i l e " , " w" )# . . . wr i t e t o t h e f i l e . . .f i l e . c l o s e

    e n d

    In the above, if an exception occurred during the section of code where we were writing to the file, the filewould be left open. And we don't want to resort to this kind of redundancy:

    b e g i nf i l e = o p e n ( " / t mp / s o me _ f i l e " , " w" )# . . . wr i t e t o t h e f i l e . . .f i l e . c l o s e

    r e s c u ef i l e . c l o s e

    f a i l # r a i s e a n e x c e p t i o ne n d

    It's clumsy, and gets out of hand when the code gets more complicated because we have to deal with everyand .

    For this reason we add another keyword to the " " scheme, which is . Thecode block executes regardless of the success or failure of the block.

    b e g i nf i l e = o p e n ( " / t mp / s o me _ f i l e " , " w" )# . . . wr i t e t o t h e f i l e . . .

    r e s c u e# . . . h a n d l e t h e e x c e p t i o n s . . .

    e n s u r ef i l e . c l o s e # . . . a n d t h i s a l wa y s h a p p e n s .

    e n d

    It is possible to use without , or vice versa, but if they are used together in the same

    block, the must precede the .

    Page 59 :

  • 7/31/2019 Ruby User's Guide

    60/68

    y User's Guide - Accessors 1 4

    eHome Workstation 2006/10/29 07:45

    Accessors

    Page 60 :

  • 7/31/2019 Ruby User's Guide

    61/68

    y User's Guide - Accessors 2 4

    eHome Workstation 2006/10/29 07:45

    We briefly discussed instance variables in an earlier chapter, but haven't done much with them yet. Anobject's instance variables are its attributes, the things that generally distinguish it from other objects of thesame class. It is important to be able to write and read these attributes; doing so requires methods calledattribute accessors . We'll see in a moment that we don't always have to write accessor methods explicitly, butlet's go through all the motions for now. The two kinds of accessors arewriters and readers .

    r u b y >|||||||

    r u b y >

    r u b y >

    r u b y >

    r u b y >

    Simple enough; we can store and retrieve information about what kind of fruit we're looking at. But ourmethod names are a little wordy. The following is more concise, and more conventional:

    r u b y >|||||

    ||

    r u b y >

    r u b y >

    r u b y >

    A short digression is in order. You've noticed by now that when we try to look at an object directly, we areshown something cryptic like . This is just a default behavior, and we are free to

    Page 61 :

  • 7/31/2019 Ruby User's Guide

    62/68

    y User's Guide - Accessors 3 4

    eHome Workstation 2006/10/29 07:45

    change it. All we need to do is add a method named . It should return a string that describes theobject in some sensible way, including the states of some or all of its instance variables.

    r u b y >||||

    r u b y >

    A related method is (convert to string), which is used when printing an object. In general, you canthink of as a tool for when you are writing and debugging programs, and as a way of refining program output. uses whenever it displays results. You can use the method toeasily get debugging output from programs.

    # Th e s e t wo l i n e s a r e e q u i v a l e n t :p a n Ob j e c tp u t s a n Ob j e c t . i n s p e c t

    Since many instance variables need accessor methods, Ruby provides convenient shortcuts for the standardforms.

    Shortcut Effect

    Let's take advantage of this and add freshness information. First we ask for an automatically generated readerand writer, and then we incorporate the new information into :

    r u b y >|||||

    r u b y >

    r u b y >

    Page 62 :

  • 7/31/2019 Ruby User's Guide

    63/68

    y User's Guide - Accessors 4 4

    eHome Workstation 2006/10/29 07:45

    If nobody eats our ripe fruit, perhaps we should let time take its toll.

    r u b y >||||

    r u b y >

    r u b y >

    r u b y >

    But while playing around here, we have introduced a small problem. What happens if we try to create a thirdpiece of fruit now? Remember that instance variables don't exist until values are assigned to them.

    r u b y >

    It is the method that is complaining here, and with good reason. We have asked it to report on thekind and condition of a piece of fruit, but as yet has not been assigned either attribute. If we wanted to,we could rewrite the method so it tests instance variables using the method and thenonly reports on them if they exist, but maybe that's not very useful; since every piece of fruit has a kind and

    condition, it seems we should make sure those always get defined somehow. That is the topic of the nextchapter.

    Page 63 :

  • 7/31/2019 Ruby User's Guide

    64/68

    y User's Guide - Object initialization 1 2

    eHome Workstation 2006/10/29 07:43

    Object initialization

    Our Fruit class from the previous chapter had two instance variables, one to describe the kind of fruit andanother to describe its condition. It was only after writing a custom method for the class that werealized it didn't make sense for a piece of fruit to lack those characteristics. Fortunately, ruby provides away to ensure that instance variables always get initialized.

    Whenever Ruby creates a new object, it looks for a method named and executes it. So onesimple thing we can do is use an method to put default values into all the instance variables, sothe method will have something to say.

    r u b y >|||||

    r u b y >

    There will be times when a default value doesn't make a lot of sense. Is there such a thing as a default kindof fruit? It may be preferable to require that each piece of fruit have its kind specified at the time of itscreation. To do this, we would add a formal argument to the method. For reasons we won't getinto here, arguments you supply to are actually delivered to .

    r u b y >

    |||||

    r u b y >

    r u b y >

    Above we see that once an argument is associated with the method, it can't be left off withoutgenerating an error. If we want to be more considerate, we can use the argument if it is given, or fall back to

    Page 64 :

  • 7/31/2019 Ruby User's Guide

    65/68

    y User's Guide - Object initialization 2 2

    eHome Workstation 2006/10/29 07:43

    default values otherwise.

    r u b y >|||||

    r u b y >

    r u b y >

    You can use default argument values for any method, not just . The argument list must bearranged so that those with default values come last.

    Sometimes it is useful to provide several ways to initialize an object. Although it is outside the scope of thistutorial, ruby supports object reflection and variable-length argument lists, which together effectively allowmethod overloading.

    Page 65 :

  • 7/31/2019 Ruby User's Guide

    66/68

    y User's Guide - Nuts and bolts 1 3

    eHome Workstation 2006/10/29 07:43

    Nuts and bolts

    This chapter addresses a few practical issues.

    Some languages require some kind of punctuation, often a semicolon (), to end each statement in a program.Ruby instead follows the convention used in shells like and . Multiple statements on one line must beseparated by semicolons, but they are not required at the end of a line; a linefeed is treated like a semicolon.If a line ends with a backslash ( ), the linefeed following it is ignored; this allows you to have a single logicalline that spans several lines.

    Why write comments? Although well written code tends to be self-documenting, it is often helpful to scribblein the margins, and it can be a mistake to believe that others will be able to look at your code andimmediately see it the way you do. Besides, for practical purposes, you yourself are a different person withina few days anyway; which of us hasn't gone back to fix or enhance a program after the passage of time andsaid, I know I wrote this, but what in blazes does it mean?

    Some experienced programmers will point out, quite correctly, that contradictory or outdated comments canbe worse than none at all. Certainly, comments shouldn't be a substitute for readable code; if your code isunclear, it's probably also buggy. You may find that you need to comment more while you are learning ruby,

    and then less as you become better at expressing your ideas in simple, elegant, readable code.

    Ruby follows a common scripting convention, which is to use a pound symbol () to denote the start of acomment. Anything following an unquoted , to the end of the line on which it appears, is ignored by theinterpreter.

    Also, to facilitate large comment blocks, the ruby interpreter also ignores anything between a line startingwith " " and another line starting with " ".

    # ! / u s r / b i n / e n v r u b y

    = b e g i n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    T h i s i s a c o mme n t b l o c k , s o me t h i n g y o u wr i t e f o r t h e b e n e f i to f

    h u ma n r e a d e r s ( i n c l u d i n g y o u r s e l f ) . T h e i n t e r p r e t e r i g n o r e si t .

    T h e r e i s n o n e e d f o r a ' # ' a t t h e s t a r t o f e v e r y l i n e .* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *= e n d

    Ruby's unusually high level of dynamism means that classes, modules, and methods exist only after theirdefining code runs. If you're used to programming in a more static language, this can sometimes lead to

    Page 66 :

  • 7/31/2019 Ruby User's Guide

    67/68

    y User's Guide - Nuts and bolts 2 3

    eHome Workstation 2006/10/29 07:43

    surprises.

    # Th e b e l o w r e s u l t s i n a n " u n d e f i n e d me t h o d " e r r o r :

    p u t s s u c c e s s o r ( 3 )

    d e f s u c c e s s o r ( x )x + 1

    e n d

    Although the interpreter checks over the entire script file for syntax before executing it, thecode has to actually run in order to create the method. So the order in which you

    arrange a script can matter.

    This does not, as it might seem at first glance, force you to organize your code in a strictly bottom-up fashion.When the interpreter encounters a method definition, it can safely include undefined references, as long asyou can be sure they will be defined by the time the method is actually invoked:

    # Co n v e r s i o n o f f a h r e n h e i t t o c e l s i u s , b r o k e n# d o wn i n t o t wo s t e p s .

    d e f f _ t o _ c ( f )s c a l e ( f - 3 2 . 0 ) # T h i s i s a f o r wa r d r e f e r e n c e , b u t i t ' s

    o k a y .e n d

    d e f s c a l e ( x )x * 5 . 0 / 9 . 0

    e n d

    p r i n t f " %. 1 f i s a c o mf o r t a b l e t e mp e r a t u r e . \ n " , f _ t o _ c ( 7 2 . 3 )

    So while this may seem less convenient than what you may be used to in Perl or Java, it is less restrictive thantrying to write C without prototypes (which would require you to always maintain a partial ordering of whatreferences what). Putting top-level code at the bottom of a source