572 lines
15 KiB
HTML
572 lines
15 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Programming in Ruby, part 1 LG #81</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<CENTER>
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
|
|
WIDTH="600" HEIGHT="124" border="0"></A>
|
|
<BR>
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="padala.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue81/ramankutty.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="sandeep.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
<P>
|
|
</CENTER>
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4 ALIGN="center">
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">Programming in Ruby, part 1</font></H1>
|
|
<H4>By <a href="mailto:hiran_rk@rediffmail.com">Hiran Ramankutty</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<H2><B> Introduction </B></H2>
|
|
<p>
|
|
<p><TD align=right><TD align=left>
|
|
Ruby is an interpreted, pure Object Oriented language designed by
|
|
Yukihiro Matsumoto of Japan, where it is reported to be more
|
|
popular than Python and Perl! The first part of this series is
|
|
meant to be a tutorial introduction, with more advanced stuff
|
|
in the pipeline.
|
|
</TD></TD>
|
|
<p>
|
|
Of course, I need not go through the ritual of advocating the
|
|
`advantages of Ruby compared to languages X, Y and Z' - most people
|
|
realize that each language has a unique flavour and character of
|
|
its own - whether you choose Python or Ruby for your next open
|
|
source project depends more on the peculiar affinity which you as an
|
|
individual feel for one over the other, and the availability of
|
|
standard library facilities, rather than on arcane technical
|
|
issues. So let's enjoy that unique Ruby flavour!
|
|
</p>
|
|
|
|
<H2><B>Requirements</B></H2>
|
|
<p>
|
|
I presume that your development environment is Linux and you have Ruby installed on
|
|
it. Ruby is free software, and there are no restrictions on it's usage. You can
|
|
get it from the <a href="http://www.ruby-lang.org"> Ruby Home Page </a>.
|
|
</p>
|
|
|
|
<H2><B>Hello World</B></H2>
|
|
<p>
|
|
Let's start with the mandatory `Hello, World'.
|
|
|
|
<pre>
|
|
|
|
% cat > hello.rb
|
|
print "Hello World\n"
|
|
^D
|
|
% ruby hello.rb
|
|
Hello World
|
|
%
|
|
|
|
</pre>
|
|
|
|
<H2><B>Variables</B></H2>
|
|
<p>
|
|
Categorization is done on the basis of the first character of the name of the
|
|
identifier:
|
|
<pre>
|
|
|
|
$ global variable
|
|
@ instance variable
|
|
a-z or '_' local variable
|
|
A-Z constant
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
The two `pseudo-variables' are exceptions to the above stated rule. They are `self'
|
|
and `nil'.
|
|
<ul>
|
|
<li> self refers to the currently executing object
|
|
<li> nil meaningless or FALSE or value assigned to uninitialized variables
|
|
</ul>
|
|
|
|
<p>
|
|
Both are named as if they are local variables, but they are not! We will see their
|
|
real meaning later on.
|
|
|
|
|
|
<H2><B>Global variables</B></H2>
|
|
<p>
|
|
A global variable has it's name starting with $. As such, it can be
|
|
referred to from anywhere in the program. It is to be noted that a global variable
|
|
assumes the value 'nil' before initialization. You can test this out:
|
|
|
|
<pre>
|
|
|
|
% ruby
|
|
print $foo,"\n"
|
|
$foo = 5
|
|
print $foo,"\n"
|
|
^D
|
|
%
|
|
|
|
</pre>
|
|
The interpreter responds
|
|
<pre>
|
|
|
|
nil
|
|
5
|
|
|
|
</pre>
|
|
|
|
It is possible for us to `bind' procedures to global variables,
|
|
the procedures being automatically invoked when the variable
|
|
is changed. More about this later!
|
|
|
|
<p>
|
|
Some special kinds of global variables formed with a single character following a '$'
|
|
sign are, as a collection, interpreted by Ruby as major system variables
|
|
(made read-only). Some of them are given below along with their meanings.
|
|
<ul>
|
|
|
|
<li> $! latest error message
|
|
<li> $@ location of error
|
|
<li> $_ string last read by gets
|
|
<li> $. line number last read by interpreter
|
|
<li> $& string last matched by regexp
|
|
<li> $~ the last regexp match, as an array of subexpressions
|
|
<li> $n the nth subexpression in the last match (same as $~[n])
|
|
<li> $= case-insensitivity flag
|
|
<li> $0 the name of the ruby script file
|
|
<li> $* the command line arguments
|
|
<li> $$ interpreter's process ID
|
|
<li> $? exit status of last executed child process
|
|
</ul>
|
|
|
|
<H2><B>Local variables</B></H2>
|
|
<p>
|
|
A local variable has it's name starting with a lower case letter or an '_'. Unlike
|
|
globals and instance variables, they do not assume the value 'nil', but they
|
|
behave as shown below:
|
|
<pre>
|
|
|
|
% ruby
|
|
print foo
|
|
^D
|
|
|
|
</pre>
|
|
You will get an error message:
|
|
<pre>
|
|
"undefined local variable or method 'foo' for #(object...)".
|
|
</pre>
|
|
|
|
<p>
|
|
The scope of a local variable is confined to one of
|
|
<ul>
|
|
<li> proc {....}
|
|
<li> loop {....}
|
|
<li> def .... end
|
|
<li> class .... end
|
|
<li> module .... end
|
|
<li> the entire program (unless one of the above applies)
|
|
</ul>
|
|
If we initialize a local variable in any block(or a procedure), then it remains
|
|
undefined after exiting from the loop. For example:
|
|
|
|
<pre>
|
|
|
|
def foo(n)
|
|
k = 2 * n
|
|
print "\n",k,"\n"
|
|
print defined? k,"\n"
|
|
end
|
|
|
|
foo 3
|
|
print defined? k,"\n"
|
|
^D
|
|
|
|
</pre>
|
|
The output is:
|
|
|
|
<pre>
|
|
|
|
6
|
|
local-variable
|
|
nil
|
|
|
|
</pre>
|
|
<p>
|
|
In the above example `defined?' is an operator which checks whether it's argument
|
|
is defined or not. The results "local-variable" and "nil" (to indicate false) must make it
|
|
clear.
|
|
</p>
|
|
|
|
<H2><B>Constants</B></H2>
|
|
<p>
|
|
Any name with characters following an uppercase letter is treated as a constant. But
|
|
Ruby programmers, to avoid confusion, use names with all uppercase letters. So 'Foo' as well
|
|
as 'FOO' are constants. As in case of local variables, a constant is defined by a
|
|
substitution and an access to an undefined constant or alteration of a defined constant
|
|
causes an error. Check for yourself.
|
|
|
|
<H2><B> Strings </B></H2>
|
|
<p>
|
|
Strings in ruby can be single quoted('...') or double quoted("...").
|
|
But both are different. Use double quotes if the string contains
|
|
backslash-escaped characters. Also results of evaluation are
|
|
embedded for contained expressions quoted by #{}. See examples:
|
|
</p>
|
|
<pre>
|
|
print "\n"
|
|
print '\n'
|
|
print "\001","\n"
|
|
print '\001',"\n"
|
|
print "abcd #{5*3} efg","\n"
|
|
var = " abc "
|
|
print "1234#{var}567","\n"
|
|
^D
|
|
|
|
\n
|
|
\001
|
|
abcd 15 efg
|
|
1234abc567
|
|
</pre>
|
|
<p>
|
|
We will learn more about strings in the next section, arrays. This is to
|
|
include the features that are similar and are held by both arrays and strings.
|
|
</p>
|
|
|
|
<H2><B>Arrays</B></H2>
|
|
<p>
|
|
Arrays can be quoted using '[]'. One of the features of Ruby is that arrays
|
|
are heterogenous.
|
|
|
|
<pre>
|
|
|
|
a = [1,2,"3"]
|
|
print a,"\n"
|
|
^D
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
Now, if you write a Ruby program to add all the elements of the array shown in the
|
|
above program, you will get an error:
|
|
<pre>
|
|
Error!!String cannot be coerced into Fixnum
|
|
</pre>
|
|
The `3' in the array is stored as a string. Now, if it is done like this:
|
|
|
|
<pre>
|
|
|
|
a = [1,2,"3"]
|
|
b = a[0] + a[1] + a[2].to_i
|
|
print b,"\n"
|
|
^D
|
|
|
|
</pre>
|
|
The program will be executed without any errors. The attachment to a[2] i.e. '.to_i'
|
|
is to convert the content of a[2] to an integer.You can also try '.to_s'.
|
|
|
|
<p>
|
|
Operations like concatenation and repetition can be done on arrays.
|
|
<pre>
|
|
|
|
a = [1,2,"3"]
|
|
print a + ["foo","bar"]
|
|
print a * 2
|
|
^D
|
|
|
|
</pre>
|
|
We get
|
|
<pre>
|
|
|
|
123foobar
|
|
123123
|
|
|
|
</pre>
|
|
<p>
|
|
It's possible to `slice and dice' arrays. Here are some examples:
|
|
<pre>
|
|
|
|
a = [1,2,"3","foo","bar"]
|
|
print a[0],"\n"
|
|
print a[0,2],"\n"
|
|
print a[0..3],"\n"
|
|
print a[-2..2],"\n"
|
|
print a[-3..-1],"\n"
|
|
|
|
</pre>
|
|
</p>
|
|
|
|
<p>
|
|
Arrays and strings are inter-convertible. An array can be converted to a string
|
|
with 'join', and a string is split up into an array with 'split'.
|
|
<pre>
|
|
|
|
a = [1,2,3]
|
|
print a[2],"\n"
|
|
a = a.join(":")
|
|
print a[2],"\n"
|
|
print a,"\n"
|
|
a = a.split(":")
|
|
print a[2],"\n"
|
|
print a,"\n"
|
|
^D
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
The Associative Array is another important data structure - it's also
|
|
called a `hash' or a `dictionary'. It's basically a name-value mapping,
|
|
as shown below:
|
|
<pre>
|
|
|
|
h = {1 => 2, "2" => "4"}
|
|
print hash,"\n"
|
|
print hash[1],"\n"
|
|
print hash["2"],"\n"
|
|
print hash[5],"\n"
|
|
^D
|
|
|
|
</pre>
|
|
I hope the results are convincing!
|
|
</p>
|
|
|
|
<H2><B>Control structures</B></H2>
|
|
|
|
<H3><B>If - else</B></H3>
|
|
<p>
|
|
Let us write the factorial function.The mathematical
|
|
definition is:
|
|
|
|
<pre>
|
|
|
|
n! = 1 (when n==0)
|
|
n! = n * (n-1)! (otherwise)
|
|
|
|
</pre>
|
|
In ruby this can be written as:
|
|
<pre>
|
|
|
|
def fact(n)
|
|
if n == 0
|
|
1
|
|
else
|
|
n * fact(n-1)
|
|
end
|
|
end
|
|
print fact 4,"\n"
|
|
|
|
</pre>
|
|
You get 24.
|
|
|
|
<p>
|
|
|
|
Ruby has been called `Algol like' because of the repeated
|
|
occurrence of `end'. In this recursive call, you may notice the
|
|
lack of the return statement. In fact, use of return is
|
|
permissible but unnecessary because a ruby function returns
|
|
the last evaluated expression (does this sound a wee bit
|
|
Lispish? If you insist, you sure can do Lisp in Ruby!)
|
|
|
|
</p>
|
|
|
|
<H3><B>The for loop</B></H3>
|
|
|
|
<p>
|
|
<pre>
|
|
|
|
for i in 0..4
|
|
body-of-for
|
|
end
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
Here i is the variable and 0..4 is the range.In the case of
|
|
strings, you can very well write:
|
|
<pre>
|
|
|
|
for i in "abc"
|
|
|
|
</pre>
|
|
|
|
|
|
<H3><B>The while loop</B></H3>
|
|
<p>
|
|
Try this out
|
|
</p>
|
|
<pre>
|
|
i=0
|
|
while i < 10
|
|
print i+=1,"\n"
|
|
end
|
|
</pre>
|
|
|
|
<H3><B> Case </B></H3>
|
|
<p>
|
|
We use the case statement to test a sequence of conditions. Try this out.
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
i = 7
|
|
case i
|
|
when 1,2..5
|
|
print "i in 2 to 5\n"
|
|
when 6..10
|
|
print "i in 6 to 10\n"
|
|
end
|
|
^D
|
|
</pre>
|
|
<p>
|
|
You get
|
|
</p>
|
|
<pre>
|
|
i in 6 to 10
|
|
</pre>
|
|
<p>
|
|
2..5 means the range including 2 and 5. It checks whether i falls
|
|
within that range.
|
|
</p>
|
|
<p>
|
|
This can be applied to strings as shown below.
|
|
</p>
|
|
<pre>
|
|
case 'abcdef'
|
|
when 'aaa','bbb'
|
|
print 'contains aaa or bbb \n"
|
|
when /def/
|
|
print "contains def \n"
|
|
end
|
|
^D
|
|
contains def
|
|
</pre>
|
|
<p>
|
|
Note the slash used with "def". It is used for quoting a regular expression.
|
|
We shall see it later.
|
|
</p>
|
|
|
|
<H3><B> Modifications with control structures </B></H3>
|
|
|
|
<p>
|
|
The case statement mentioned just above actually tests for the range
|
|
(i in 2..5) as
|
|
</p>
|
|
<pre>(2..5) === i </pre>
|
|
<p>The relationship operator '===' is used by case to check for several
|
|
conditions at a time. '===' is interpreted by ruby suitably for the
|
|
object that appears in the when condition.
|
|
</p>
|
|
<p>
|
|
Thereby in the example with strings equality is tested with first when
|
|
and an expression is matched with the second when.
|
|
</p>
|
|
<p>
|
|
Now try using the operator '===' with if structure(try implementing
|
|
functions like isalnum(),isalpha(),isnum() etc.).
|
|
</p>
|
|
|
|
<p>
|
|
Your code can be shortened when we have to use if and while constructs
|
|
for individual statements: as shown below
|
|
</p>
|
|
<pre>
|
|
i = 7
|
|
print "contained in 5..10\n" if (5..10) === i
|
|
print i-=1,"\n" while i > 0
|
|
^D
|
|
contained in 5..10
|
|
6
|
|
5
|
|
4
|
|
3
|
|
2
|
|
1
|
|
0
|
|
</pre>
|
|
<p>
|
|
You may at times want to negate the test conditions. An unless is
|
|
a negated if, and an until is a negated while. This is left up to you to
|
|
experiment with.
|
|
</p>
|
|
<p>
|
|
There are four ways to interrupt the processing of statements of a loop
|
|
from inside. First, as in C, break means, to escape from the loop
|
|
entirely. Second, next skips to beginning of the next iteration of the
|
|
loop (corresponds to continue statement in C). Third ruby has redo,
|
|
which restarts the current iteration. The following is C code
|
|
illustrating the meanings of break, next, and redo:
|
|
</p>
|
|
<pre>
|
|
while(condition) {
|
|
label_redo:
|
|
goto label_next; /* ruby's "next" */
|
|
goto label_break; /* ruby's "break"*/
|
|
goto label_redo; /* ruby's "redo" */
|
|
...
|
|
...
|
|
label_next:
|
|
}
|
|
label_break:
|
|
...
|
|
</pre>
|
|
<p>
|
|
The return statement is actually the fourth way to get out of a loop
|
|
from inside. In fact return causes escape not only from the loop
|
|
but also from the method that contains the loop.
|
|
</p>
|
|
|
|
|
|
<H2><B> Conclusion </B></H2>
|
|
We have examined some elementary language features - enough to get
|
|
you started with a bit of `quick-and-dirty' coding. As I learn more
|
|
about this `gem' of a language, I shall be sharing my experience
|
|
with you through future articles. Good bye!
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN bio *** -->
|
|
<SPACER TYPE="vertical" SIZE="30">
|
|
<P>
|
|
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Hiran Ramankutty</H4>
|
|
<EM>I am a final year student of Computer Science at Government Engineering
|
|
College, Trichur. Apart from Linux, I enjoy learning Physics.</EM>
|
|
|
|
|
|
<!-- *** END bio *** -->
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<P> <hr> <!-- P -->
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 2002, Hiran Ramankutty.<BR>
|
|
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
|
|
Published in Issue 81 of <i>Linux Gazette</i>, August 2002</H5>
|
|
<!-- *** END copyright *** -->
|
|
|
|
<!--startcut ==========================================================-->
|
|
<HR><P>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="padala.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue81/ramankutty.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="sandeep.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|