Ruby的简单例子

02:48下午 三月 05, 2008 in category Ruby语言 by Ruby-红宝石

让我们写个函数计算阶乘。数学上阶乘的定义为:

n 的阶乘:

n! = 1                (当 n==0)
   = n * (n-1)!       (否则)

在ruby里, 这个可以写为:

def fact(n)
  if n == 0
    1
  else
    n * fact(n-1)
  end
end

你会注意到在结尾重复的end。Ruby被称作"Algol-like"就是因为这个。(实际上ruby的语法更像Eiffel语言。)你可能注意到函数缺少一个返回声明。它是不需要的,因为ruby总是返回其最后计算的东西。在这里使用一个return声明是允许的但不是必须的。

让我们来测试这个函数,在添加一行代码来运行程序:

# Program to find the factorial of a number
# Save this as fact.rb

def fact(n)
  if n == 0
    1
  else
    n * fact(n-1)
  end
end

puts fact(ARGV[0].to_i)

这里, ARGV是一个包含命令行参数的数组,to_i 转换一个字符串到一个整数。

% ruby fact.rb 1
1
% ruby fact.rb 5
120

使用40做参数可以运行吗?它将会使你的计算器溢出...

% ruby fact.rb 40
815915283247897734345611269596115894272000000000

它可以运行。实际上,ruby可以处理你计算机内存允许的任意一个整数。因此 400!也可以被计算出来:

% ruby fact.rb 400
64034522846623895262347970319503005850702583026002959458684
44594280239716918683143627847864746326467629435057503585681
08482981628835174352289619886468029979373416541508381624264
61942352307046244325015114448670890662773914918117331955996
44070954967134529047702032243491121079759328079510154537266
72516278778900093497637657103263503315339653498683868313393
52024373788157786791506311858702618270169819740062983025308
59129834616227230455833952075961150530223608681043329725519
48526744322324386699484224042325998055516106359423769613992
31917134063858996537970147827206606320217379472010321356624
61380907794230459736069956759583609615871512991382228657857
95493616176544804532220078258184008484364155912294542753848
03558374518022675900061399560145595206127211192918105032491
00800000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000

看一眼并不能判断上面的结果是正确的,但是它应该是正确的,哈哈。

输入/求值 环路

当你不带参数运行ruby的时候,它从标准输入中读取命令,在输入的结尾计算它们:

% ruby
puts "hello world"
puts "good-bye world"
^D
hello world
good-bye world

上面的^D代表 Ctrl-D, 在Unix环境下结束输入的简便方法。在DOS/Windows下, 尝试用 F6 或者 ^Z 代替.

Ruby也附带了一个名为eval.rb的程序,允许从键盘交互式输入ruby代码并显示结果。我们将在这个指南的后面大量地使用它。

如果你有一个ANSI兼容的终端(如果你正在使用UNIX,基本都是ANSI兼容终端;在某些旧版本的DOS,你需要安装ANSI.SYS 或 ANSI.COM; 如果是Windows XP,很不幸,这几乎就不可能了),你应该使用这个增强的 eval.rb 来增加可视化的辅助,错误警告,和颜色加亮。另外,你可以在ruby发布里的例子子目录找到适合任何终端的非ANSI兼容的版本。下面是一个简短的eval.rb会话:

% ruby eval.rb
ruby> puts "Hello, world."
Hello, world.
   nil
ruby> exit

hello world 是 puts 生成的。下一行, 在这里是nil, 报告哪里求值结束;ruby不能够区分声明和表达式,因此求值一个代码片段和执行它是一回事。这里,nil表示puts没有返回一个有意义的值。我们可以输入exit退出解释器,虽然你也可以使用 ^D 。

贯穿这个指南,"ruby>"用来指示我们的游泳的小eval.rb程序的提示。

eval.rb内容:

#!/usr/local/bin/ruby

#######################################################
#
# Ruby interactive input/eval loop
# Written by matz (matz@netlab.co.jp)
# Modified by Mark Slagell (slagell@ruby-lang.org)
# with suggestions for improvement from Dave Thomas
# (Dave@Thomases.com)
#
#######################################################
#
# NOTE - this file has been renamed with a .txt extension to
# allow you to view or download it without the rubyist.net
# web server trying to run it as a CGI script. You will
# probably want to rename it back to eval.rb.
#
#######################################################

module EvalWrapper

# Constants for ANSI screen interaction. Adjust to your liking.
Norm = "\033[0m"
PCol = Norm # Prompt color
Code = "\033[1;32m" # yellow
Eval = "\033[0;36m" # cyan
Prompt = PCol+"ruby> "+Norm
PrMore = PCol+" | "+Norm
Ispace = " " # Adjust length of this for indentation.
Wipe = "\033[A\033[K" # Move cursor up and erase line

# Return a pair of indentation deltas. The first applies before
# the current line is printed, the second after.
def EvalWrapper.indentation( code )
case code
when /^\s*(class|module|def|if|case|while|for|begin)\b[^_]/
[0,1] # increase indentation because of keyword
when /^\s*end\b[^_]/
[-1,0] # decrease because of end
when /\{\s*(\|.*\|)?\s*$/
[0,1] # increase because of '{'
when /^\s*\}/
[-1,0] # decrease because of '}'
when /^\s*(rescue|ensure|elsif|else)\b[^_]/
[-1,1] # decrease for this line, then come back
else
[0,0] # we see no reason to change anything
end
end

# On exit, restore normal screen colors.
END { print Norm,"\n" }


##############################################################
# Execution starts here.
##############################################################

indent=0
while TRUE # Top of main loop.

# Print prompt, move cursor to tentative indentation level, and get
# a line of input from the user.
if( indent == 0 )
expr = ''; print Prompt # (expecting a fresh expression)
else
print PrMore # (appending to previous lines)
end
print Ispace * indent,Code
line = gets
print Norm

if not line
# end of input (^D) - if there is no expression, exit, else
# reset cursor to the beginning of this line.
if expr == '' then break else print "\r" end
else

# Append the input to whatever we had.
expr << line

# Determine changes in indentation, reposition this line if
# necessary, and adjust indentation for the next prompt.
begin
ind1,ind2 = indentation( line )
if( ind1 != 0 )
indent += ind1
print Wipe,PrMore,(Ispace*indent),Code,line,Norm
end
indent += ind2
rescue # On error, restart the main loop.
print Eval,"ERR: Nesting violation\n",Norm
indent = 0
redo
end

# Okay, do we have something worth evaulating?
if (indent == 0) && (expr.chop =~ /[^; \t\n\r\f]+/)
begin
result = eval(expr, TOPLEVEL_BINDING).inspect
if $! # no exception, but $! non-nil, means a warning
print Eval,$!,Norm,"\n"
$!=nil
end
print Eval," ",result,Norm,"\n"
rescue ScriptError,StandardError
$! = 'exception raised' if not $!
print Eval,"ERR: ",$!,Norm,"\n"
end
break if not line
end
end
end # Bottom of main loop
print "\n"

end




评论[0]

评论:

发表一条评论:
  • HTML语法: 启用