现在我们将前面的一些示例程序的代码坼开来分析一下.
下面的例子出现在简单的例子一节.
deffact(n)
ifn==0
1
else
n*fact(n-1)
end
end
printfact(ARGV[0].to_i),"n"
因为是第一次解释,我们将逐行分析.
deffact(n)
第一行,def用于定义一个函数(或者,更准确地说,一个方法(method);我们会在稍后的一节中详细讨论什么是一个方法).这里,它指明fact函数带一个参数,也就是n.
ifn==0
if用来检查一个条件.当条件吻合时,执行下面的代码;否则执行跟在else后的代码.
1
当条件成立时if的值为1.
else
如果条件不成立,执行从这里到end的代码.
n*fact(n-1)
如果条件不满足,if的值会是n乘fact(n-1)的结果.
end
第一个end与if语句对应.
end
第二个end与def语句对应.
printfact(ARGV[0].to_i),"n"
这句用由命令行指定的值来调用fact()函数并打印结果.
ARGV是一个包含命令行参数的数组.ARGV的成员是字符串,所以我们必须通过to_i转化其为整数.Ruby并不像Perl那样自动将字符串转化为整数.
Hmmm...如果向程序赋一个负值作为参数会怎样?你看到这个问题了吗?你可以修复它吗?
Strings
下面我们来检查在字符串这章中出现的猜谜程序.由于这个要长一点,我们为每一行打上行数.
01words=['foobar','baz','quux']
02secret=words[rand(3)]
03
04print"guess?"
05whileguess=STDIN.gets
06guess.chop!
07ifguess==secret
08print"youwinn"
09break
10else
11print"youlose.n"
12end
13print"guess?"
14end
15print"thewordis",secret,".n"
这个程序里,我们使用了一个新的控制结构while.只要某个指定的条件保持为真,while和它对应的end之间的代码会重复执行.
行2的rand(3)返回一个介于0-2之间的随机数.这个随机数用于提取数组words中的一个成员.
在行5我们通过STDIN.gets方法从标准输入读取一行.如果读行遇到时EOF(文件结束),gets会返回nil.因此,与while相连的代码会一直执行直到它遇到^D(或DOS下的^Z),表示输入的结束.
行6的guess.chop!去掉guess的最后一个字符;那一定是个换行符.
行15,我们打印出要猜的词.我们写的代码是上向print语句传递三个参数(这三个参数一个接一个地打印),但也可以用一个参数等效地打印:将secret写为#{secret}以表明将它是一个要取值的变量,而非一个要打印的一般文字:
print"thewordis#{secret}.n"
正则表达式
最后我们来看看正则表达式一节的那个程序.
01st="33[7m"
02en="33[m"
03
04whileTRUE
05print"str>"
06STDOUT.flush
07str=gets
08breakifnotstr
09str.chop!
10print"pat>"
11STDOUT.flush
12re=gets
13breakifnotre
14re.chop!
15str.gsub!re,"#{st}"
16printstr,"n"
17end
18print"n"
在行4,while的条件被硬设为true,因此这好像构成了一个无限循环.但我们在行8和行13放置了break语句以跳出循环.这两个break语句也是if修饰辞(ifmodifier)的一个例子.一个"if修饰辞"当且仅当指明条件满足时执行它左边的语句.
再说说chop!(出现在行9和行14).在Ruby里,我们亦可将"!"和"?"附于某些方法名字后面.惊叹号(!,有时大声地念作"bang!")暗示某些东西可能具破坏性(destructive),也就是指,某些东西可以改变它所触及的东西.chop!直接作用于一个字符串,但不带!的chop只会产生一个拷贝.下面有这一区别的演示.
ruby>s1="forth"
"forth"
ruby>s1.chop!#Thischangess1.
"fort"
ruby>s2=s1.chop#Thisputsachangedcopyins2,
"for"
ruby>s1#...withoutdisturbings1.
"fort"
以后你还会遇见以问号(?,有时大声地念做"huh?")结束的方法名;这指"断言"(prediacte)方法,只会返回true或false.
行15应给予注意.首先,注意gsub!也是一个破坏函数.它通过替换所有符合re模式字符来修改str(sub指替换,首字母g指全局,比如,替换所有的匹配而不只是第一个匹配).到此为止,还好;但我们用什么来替代文本中的匹配部分呢?在行1和行2里的st和en被分别定义为表示反转文本颜色(color-inverted)和恢复正常文本颜色的ANSI码.在行15,它们被#{}括起以确保他们被前面定义的那样解释(这样我们才没看见变量名被打印出来).在这中间是"&".这是个小把戏.因为替换字符串是由双引号引起的,一对反斜杠会被解释为一个单一的反斜杠;所以gsub!实际上得到的是"&",就一段特殊代码正好就是表示"任何与模式于第一处匹配的字符".因此新的字符串在被打印出来的时候,很像原来的那个,只不过匹配的部分以反视(inversevideo)的方式高亮度显示出来.