kenlistian

勤学多思

  IT博客 :: 首页 :: 新随笔 ::  :: 聚合  :: 管理 ::
  412 随笔 :: 0 文章 :: 23 评论 :: 0 Trackbacks

控制语句

if

if 表达式 [then]
  表达式 ...
[elsif 表达式 [then]
  表达式 ... ]
...
[else
  表达式 ... ]
end

Ruby中只有falsenil代表伪,其他都是真,甚至0或空字符串也是如此。

if 修饰句

语法:

表达式 if 表达式
unless(除非)
语法:
unless 表达式 [then]

表达式 ...
[else 表达式 ... ]
end

unless 修饰句

语法:     表达式 unless 表达式

Case

语法:

case [表达式]
[when 表达式 [, 表达式] ...[, `*' 表达式] [then]
  表达式..]..
[when `*' 表达式 [then]
  表达式..]..
[else
  表达式..]
end
在表达式并列时是or的关系,还有*的使用,遵循以下:

若when 部分中的最后一个表达式前带"*"的话,
该表达式将被当作数组展开。

ary = [1,2,3]

case v
when *ary
 ..
end

等同于

case v
when 1, 2, 3
 ..
end
 
 
while
语法: 
  while 表达式 [do]
     ...
  end
do 可要可不要
 
while 修饰句   
语法:
   表达式 while 表达式
如: sleep(60) while io_not_ready?

until
语法:
  until 表达式 [do]
 ...
  end
在表达式的计算值变为真之前,一直循环执行until中的内容。until不返回值。
 
是先判断表达式呢还是执行后再判断?
until修饰句
  表达式 until  表达式
 
 
for 
  语法:
for lhs ... in 表达式 [do]
  表达式
end
<===>
(表达式).each '{' '|' lhs.. '|' 表达式.. '}'
 
--------------------------------------------------------------------
break
退出循环,循环有下列:
while
until
for
迭代
 
next
next将跳转到最内侧循环的头部,像continue;
 
redo
  不检查循环条件,重新开始当前循环
 
retry

在迭代、块或for语句中使用retry,意味着重启迭代器。
同时迭代器的参数也将被重新计算。

for i in 1..5
  retry if some_condition # 从 i == 1 开始重新执行
end

# 用户定义的 "until循环"
def UNTIL(cond)
  return if cond
  yield
  retry
end
 
---------------------------------------------------------
异常处理语句
raise

例:

   raise "you lose"  # 引发RuntimeError异常
   
# 下面两个将引发SyntaxError异常
raise SyntaxError, "invalid syntax"
raise SyntaxError.new("invalid syntax")
raise                 # 再次引发上一个异常

语法:

raise
raise message或exception
raise error_type, message
raise error_type, message, traceback

引发异常。

第一句将再次引发上一个异常。

第二句中,若参数是字符串的话,就把它当作错误信息(message)再引发RuntimeError异常。

若参数为异常对象则引发该异常。

第三句中,将引发第一个参数所指的异常,并以第二个参数的内容作为错误信息。

第四句中,第三参数装载的是源自于$@caller的堆栈信息,它指明发生异常的地点。

可以使用begin表达式的rescue部分来捕捉异常。这时使用rescue error_type => var就可以得到异常对象。您还可以从内部变量$!中获得这个对象。另外,变量$@中装载的是发生异常的源代码位置。

raise并不是Ruby的保留字,它是Kernel模块中定义的函数式的方法。

 

 

begin

异常处理的开始,

这个其实就像try catch finally一样,

其中

rescue === catch

ensure === finally

 

语法:

begin
  表达式..
[rescue [error_type,..] [=> evar] [then]
  表达式..]..
[else
  表达式..]
[ensure
  表达式..]
end

 

若给出了rescue部分(可以有若干个)的话,就可以在发生异常时捕捉到它。

若存在与异常类型一致的rescue部分的话,就执行rescue的内容。

可以使用$!来查看异常的情况。另外,若事先设定了变量evar的话,

它也可以像$!一样存储那些异常的信息。

begin
  raise "error message"
rescue => evar
  p $!
  p evar
end
# => #<RuntimeError: error message>
     #<RuntimeError: error message>

rescue部分使用Object#kind of?来判断刚才的异常的类是否就是自己期待的异常类,

或者这二者是否处于父类/子类的关系。

error_type被省略,则将捕捉StandardError的子类中的所有异常。

 

Ruby的内部异常(除了SystemExitInterrupt这些退出命令以外)

StandardError的子类。

 

请参考异常类来了解异常类的层次关系。

rescue部分中,error_type与普通的参数一样接受计算,若符合的话就执行

相应部分的内容。

error_type的计算值既非类又非模块的话,则引发TypeError异常。

若运行过程中没发生异常,则开始计算可选的else部分。

若存在ensure部分的话,则在begin表达式结束之前一定会计算它。

 

begin表达式整体的计算值取决于,begin的内容部分/rescue部分/else部分

中最后被计算的句子的值。若各部分中均无语句时,其值为nil。不管怎样,

ensure部分的值始终会被忽略。

例:

  open("nonexistent file") 
  rescue STDERR.puts "Warning: #$!"

语法:

表达式1 rescue 表达式2

若表达式1中发生异常时就计算表达式2。这等同于下例。

不能指定想捕捉的异常类。(也就是说,只能捕捉StandardError异常类的子类了)

begin
  表达式1
rescue
  表达式2
end

在包括rescue修饰句的表达式中,若没发生异常则返回表达式1的值,

若发生异常则返回表达式2的值。但在大多数场合中,因为考虑到优先度的问题,

所以需要使用括号将整个表达式括起来。

 
var = open("nonexistent file") rescue false
p var
=> nil      # 因为只定义了一个空变量var

var = (open("nonexistent file") rescue false)
p var
=> false

是传递给某方法的参数时,有必要使用双重括号。

p(open("nonexistent file") rescue false)
=> parse error

p((open("nonexistent file") rescue false))
=> false
 
return

例:

return
return 12
return 1,2,3

语法:

return [表达式[`,' 表达式 ... ]]

结束方法的运行,且把表达式的值设定为方法的返回值。若给出了2个以上的表达式,

则将把这些表达式化为一个数组,然后把该数组设定为方法的返回值。若省略表达式,

将返回值设为nil。

 
BEGIN
 

语法:

BEGIN '{' 语句.. '}'

注册初始化例程(routine)。BEGIN块所指定的语句的执行顺序将先于该文件中任何语句。
若有多个BEGIN块的话,将按照出现顺序依次执行。

BEGIN块在编译时被注册。也就是说,同一条语句只会被注册一次。

if false
  BEGIN { p "begin" }
end

# => "begin"

BEGIN块引入了独立的局部变量作用域,因此不能和外部共享局部变量。

为了与块外交换信息,必须借助于常数或全局变量。

BEGIN { $foo, foo = true, true }
p $foo  # => true
p foo   # undefined local variable or method `foo' for main:Object (NameError)

BEGIN不能出现在方法定义表达式中,否则会引发 parse error。

def foo
  BEGIN { p "begin" }
end
# => -:2: BEGIN in method
 
END

语法:
END '{' 
语句..
'}'

注册“善后”例程。END块中指定的语句会在解释器结束前得到执行。

 

若注册了若干END块的话,则与注册时相反的顺序依次执行这些块。
END { p 1 } END { p 2 } END { p 3 } # => 3 2 1

 

 


 

 


 

 

把END块置入循环中,也只会注册一次。

5.times do |i|
  END { p i }
end
# => 0

 

若把END块置入方法定义表达式中会引起警告。

def foo
  END { p "end" }
end
p foo

# => -:2: warning: END in method; use at_exit
     nil
     "end"


END块与BEGIN块不同的是,它同周围部分共享作用域。也就是说,它的作用域同迭代器一样。

若END块中发生了异常,将中断该块。但解释器并不结束,只是发出信息,
并且试图处理完所有的善后例程。

例:

END { p "FOO" }
END { raise "bar"; p "BAR" }
END { raise "baz"; p "BAZ" }

=> baz (RuntimeError)
   bar (RuntimeError)
   "FOO"
 
posted on 2006-12-29 10:21 kenlistian 阅读(399) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。