`
阅读更多
    《Programming Ruby中文版》前3部分我并不准备细看,毕竟我接触ruby也有一段时间了,只准备快速地掠过一遍,查缺补漏;重点放在第3部分的核心内容上,至于第四部分的参考手册更多作为工具书了。仅在此记录下一些值的注意的东西。

1.全局变量$_,默认当gets方法返回输入的行时,同时保存在全局变量$_,并且正则表达式如果作为条件语句(if或者while)时默认是跟这个全局变量进行匹配,而print参数为空时也是打印这个全局变量。这是早期ruby向perl语言学习的结果。可以看看这个例子:
<!---->while gets
  
if /Ruby/
      print
  end
end

这样的风格不值的提倡,全局变量的使用应该尽力减少,ruby也在逐渐脱离perl主义的风格

2.ruby中的单例模式:
<!---->class Logger
  private_class_method:new
  @@logger
=nil
  
def Logger.create
    @@logger
=new unless @@logger
    @@logger
  end
end
log1
=Logger.create
log2
=Logger.create

puts log1.object_id
puts log2.object_id

3.ruby中的block作用:
1)迭代器,通常是内部迭代器
2)事务Blocks,c#的using语句倒是跟这个有点像,其实就是让对象自身负责资源的打开和关闭,这是通过Kernel.block_given?实现的,比如File.open方法,当后面跟着一个block的时候,就会自动关闭打开的文件资源,如果不是,就需要自己处理。
3)作为闭包,与javascript和其他语言中的闭包概念一致,一个例子:
<!---->def n_times(thing)
  
return lambda {|n| thing*n}
end
p1
=n_times(23)
puts p1.call(
3)
puts p1.call(
2)
通过lambda方法将一个block转为Proc对象,尽管参数thing在block被真正调用时已经离开了作用范围,但是仍然可以使用

4.ruby中数字的最大长度取决于系统,这跟java,C#通过虚拟机规范的不同,数字类型的几个常用迭代器:times,upto,downto,step,如:
<!---->2.step(10,2){|i| print i,' '}  =>2,4,6,8,10

5.ruby中的字符串是8字节的序列,可以存储可打印的字符和二进制数据。比较有趣3种构建字符串常量方式:%q(对应于单引号定义的字符串),%Q(双引号)以及here documents,比如:
<!---->s=<<END_OF_STRING
   测试测试啦
END_OF_STRING

6.Range,书中翻译为区间,我倒更喜欢范围这个词。区间的3个用途:
1)用作序列,最常见的,如1..2,a..z等,可以定义自己的区间,只要实现succ和<=>比较方法
2)作为条件,书中的例子很经典:
<!---->while line=gets
   puts line 
if line=~/start/..line=~/end/
end

#利用全局变量简化为,不建议这样写
while gets
   
print if /start/../end/
end

3)作为间隔,看看某个值是否落入区间范围内,使用===操作符比较

7.正则表达式,这是重头戏。ruby中的perl风格的正则表达式,其实也是内建在ruby中的正则表达式对象的外部包装,关键的就是两个类Regexp类和MatchData类。一些peri程序员熟悉的记号:
$&    匹配的字符串
$`    匹配前的字符串
$'    匹配后的字符串
$1    第一个分组,$2,$3...类似
详细的就不抄书了,正则表达式我在学习javascript的时候已经系统地学过,倒是不感觉吃力。

8.在方法中定义可变长度参数,只要参数前加*号即可,java1.5也已经支持可变参数,比如Object...obj。
另外,在方法中,将数组展开为参数,可以在数组前加一个*号,比如:
<!---->def three(a,b,c)
   
print "this is #{a},#{b},#{c}"
end

three([
1,2,3)]
#上面这样调用报参数数目错误,正确的用法如下:
three(*[1,2,3)] =>this is 1,2,3
将hash列表直接做为参数,可能在2.0支持,目前采用的要求散列数组在正常的参数之后,并位于任何的block或者数组之前

9.ruby中的多线程:
1)ruby创建线程,见下面这个例子,开3个线程分别访问3个站点,并且对3个线程通过调用join方法,直到3个线程都结束,主线程才结束,来自书中例子:
<!---->require 'net/http'
pages
=%w(www.iteye.com www.sina.com.cn www.blogjava.net)
$proxy_addr 
= 'x.x.x.x'
$proxy_port 
= 80
threads
=[]
for page_to_fetch in pages
  threads
<<Thread.new(page_to_fetch) do |url|
    h
=Net::HTTP.Proxy($proxy_addr, $proxy_port).new(url,80)
    puts 
"Fetcing:#{url}"
    resp
=h.get('/',nil)
    puts 
"Got #{url}:#{resp.message}"
  end
end    
threads.each{
|thr| thr.join}

2)线程中如何共享变量?可以通过[]=简单地把当前线程看成一个散列表,这里没有考虑同步问题:
<!---->count=0
threads
=[]
10.times do |i|
  threads[i]
=Thread.new do 
    sleep(rand(
0.1))
    Thread.current[
"mycount"]=count
    count
+=1
  end
end
threads.each{
|t| t.join;print t["mycount"],""}
puts 
"count =#{count}"

3)通过设置abort_on_exception,如果是true,未处理的线程异常将杀死所有正在运行的线程,如果是false,则杀死当前运行的线程,其他线程继续运行。修改上面的例子查看下:
<!---->count=0
threads
=[]
10.times do |i|
  threads[i]
=Thread.new(i) do |j|
    
raise "boom!" if j==4 
    sleep(rand(
0.1))
    Thread.current[
"mycount"]=count
    count
+=1
  end
end
threads.each do 
|t|
  begin
    t.join
    
print t["mycount"],""
  rescue RuntimeError
=>e
    puts 
"Failed:#{e.message}"
  end
end
puts 
"count =#{count}"
输出(随机的):
8, 1, 6, 3, Failed:boom!
2, 4, 7, 0, 5, count =9

在开头加上:
<!---->Thread.abort_on_exception=true
杀死所有的运行进程,报出异常,而不会产生输出。

4)通过线程的一系列方法:pass,join,value,stop来进行线程的调度
5)互斥的实现,与其他语言一样,不外乎加锁、信号量、队列的方式。看看加锁是如何做的,通过monitor库的关键字synchronize实现,如下面这个例子,两个线程递增同一个变量,似乎结果应该是20000:
<!---->#require 'monitor'
class Counter#<Monitor
  attr_reader:count
  
def initialize
    @count
=0
  
#  super
  end
  
def tick
  
#  synchronize do
      @count+=1
  
#  end
  end
end
c
=Counter.new
t1
=Thread.new{10000.times{c.tick}}
t2
=Thread.new{10000.times{c.tick}}

t1.join;t2.join

print c.count
很遗憾,结果不会是20000,而是比它小的一个数值,这里的问题就是因为访问共享资源没有进行同步的缘故,使用monitor库,请将上面代码中的注释去掉,可以得到正确的结果
使用monitor,不一定要使用继承,也可以使用mixin,甚至:
<!---->lock=Monitor.new
t1
=Thread.new{10000.times{lock.synchronize{c.tick}}}
还可以把特定的对象放入monitor,比如:
<!---->c=Counter.new
c.extend(MonitorMixin)
t1
=Thread.new{10000.times{c.synchronize{c.tick}}}
.

6)条件变量和队列的方式不准备抄书了,ruby中对线程的操作都是直接调用操作系统的命令,特别是*nix支持的非常好,可惜我对linux也是个初哥。

10.ruby中表达式很重要的一个特点是:任何表达式都有返回值,包括赋值语句、条件语句、循环语句之类。
1)ruby中对布尔表达式的规定是:任何不是nil或者常量false的值都为真
2)注意,在方法中调用访问属性的函数,需要写上调用者self,否则将处理为局部变量
3)defined?方法用于返回参数的描述,如果未定义,返回nil
4)逻辑表达式中,and和or的优先级低于&&,||
5)ruby没有for语句,因为ruby通过内建在对象中的迭代器提供了循环访问的能力,最简单的内建迭代器:loop do ....end
6)只要你的类支持each方法,你就可以使用for ... in ..语句循环它
7)对循环可以使用break(打断跳出),redo(从头重新循环,当前迭代),next进行调度。另外,还有retry,用于完全重新开始循环
8)while,until和for循环内建到了ruby语言中,但没有引入新的作用域:前面存在的局部变量可以在循环中使用,而循环中新创建的局部变量也可以在循环后使用。而被迭代器使用的block则不同,在block中创建的局部变量无法在block外访问。

11.ruby的异常处理
类似于java的try...catch...finnaly,ruby对应的是begin...rescue...ensure...end,将产生异常的代码放在这个块中进行处理。可以通过$!得到异常信息,或者提供局部变量名,我改写了一下我的google在线翻译机,增加异常处理,并用exit代替break:
<!---->require 'net/http'
def translate
  txt
=STDIN.gets
  exit 
if txt.strip=='e' or txt.strip=='exit'
  temp
=txt.split(' ')
  
if temp[1]=='1' or temp.size==1
    langpair
='en|zh-CN'
  
else
    langpair
='zh-CN|en'
  end
  
#使用代理  
  begin 
    $proxy_addr 
= 'localhost'
    $proxy_port 
= 80
    response 
= Net::HTTP.Proxy($proxy_addr,$proxy_port).post_form(URI.parse("http://translate.google.com/translate_t"),{'text'=>temp[0],'langpair'=>langpair})
    response.body 
=~ /<div id=result_box dir=ltr>(.*)<\/div>/
  rescue  StandardError 
=>e
    $stderr.
print "网络错误:"+e
  
else
    result 
= $1 
    puts 
'翻译内容:'+temp[0]
    puts 
'google返回:'+result
    puts 
'-------------------退出请打e或者exit---------------'
    translate
  end
end
translate
引发一个异常使用raise语句,重新引发当前异常,如果没有,就引发一个RuntimeError,常见使用方式:
<!---->raise InterfaceException,"keyboard failure",caller
其中的caller生成了栈的信息。另外,catch...throw语句用于在异常发生时从深度嵌套的结构中跳转出来。

12。关于模块,作用有二:作为命名空间和Mixin机制。模块的Mixin机制可以说是ruby的一个精华所在,通过Mixin,可以变相地实现了多重继承,并且可以动态地为类添加和删除功能。这一部分注意两点:
1)模块中定义的实例变量可能与包含模块的类的实例变量产生名称冲突。可以使用模块一级的散列表,以当前对象的ID做索引,来保存特定于当前模块的实例变量解决这个问题。比如:
<!---->module Test
  State
={}
  
def state=(value)
    State[object_id]
=value
  end
  
def state
    State[object_id]
  end
end
class Client
  include Test
end
c1
=Client.new
c2
=Client.new
c1.state
='A'
c2.state
='B'

puts c1.state
puts c2.state
2)是关于方法的查找路径,顺序是:当前类-》类的mixin模块-》超类-》超类的mixin,另外mixin的模块,最后混入的同名方法将覆盖前面混入的。



















dennis 2007-04-07 10:30 发表评论
分享到:
评论

相关推荐

    ruby查缺补漏 - 庄周梦蝶 - BlogJava 1

    ruby查缺补漏 - 庄周梦蝶 - BlogJava

    Ruby Ruby Ruby Ruby Ruby Ruby

    Ruby Ruby Ruby Ruby Ruby Ruby

    Ruby-rubybuild编译和安装Ruby

    Ruby是一种动态、开源的编程语言,以其简洁、优雅的语法和强大的元编程能力著称。在Ruby开发中,为了管理不同版本的Ruby环境,我们常常会使用到`rbenv`和`ruby-build`这两个工具。本文将详细介绍如何使用`ruby-build...

    Ruby-rubyinstall安装RubyJRubyRubiniusMagLevorMRuby

    Ruby是一种强大的、面向对象的脚本语言,广泛用于...对于那些需要在不同Ruby实现间切换的开发者来说,这是一个不可或缺的工具。通过熟练掌握`ruby-install`的使用,可以更好地适应不断变化的开发需求,提高开发效率。

    ruby DBI ruby DBI ruby DBI

    ruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ...

    Ruby完全自学手册 下

    《Ruby完全自学手册》是一本完全覆盖Ruby和Ruby on Rails的完全自学手册。《Ruby完全自学手册》的特色是由浅入深、循序渐进,注重理论和实践的结合。虽然定位为入门手册,但是依然涉及许多高级技术和应用,覆盖到的...

    src-oepkgs/ruby-ruby2ruby

    src-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2...

    Ruby完全自学手册

    Ruby是一种简洁而功能强大的编程语言,由日本的松本行弘(Yukihiro "Matz" Matsumoto)在1993年开发,并于1995年公开发布。Ruby语言设计之初就非常注重开发人员的编程体验,它拥有自然、表达性强的语法,易于阅读和...

    Ruby新手学习书(Ruby语言中文教程)和Rails_4_days

    Ruby是一种面向对象的编程语言,以其简洁、优雅的语法著称,被广泛应用于Web开发,尤其是与Ruby on Rails框架结合使用。"Ruby新手学习书"和"Rails_4_days"这两个资源是为初学者设计的,旨在帮助他们快速掌握Ruby语言...

    ruby安装包下载 | ruby环境搭建

    Ruby是一种强大的动态编程语言,广泛应用于Web开发,脚本编写,服务器管理等领域。为了在没有外网连接的环境中搭建Ruby环境,你需要提前下载并准备相关的安装包。在提供的压缩包中,包含了三个关键文件:`ruby-2.7.2...

    Ruby-Mobility可拔插的Ruby翻译框架

    Ruby-Mobility是一款强大的、可拔插的Ruby翻译框架,专为解决多语言支持而设计。这个框架的主要目标是提供一种灵活、高效且易于集成的方式来处理应用中的国际化(i18n)问题。Ruby-Mobility的核心设计理念在于解耦...

    ruby-runtime手动插件.zip

    在 Jenkins 集成环境中,如果你的持续集成或持续部署流程中涉及 Ruby 语言的项目,比如 Rails 应用,那么这款插件就显得不可或缺。Ruby Runtime 插件允许你在 Jenkins 中配置和管理不同的 Ruby 版本,确保你的构建...

    ruby2ruby.zip

    ruby2ruby 提供一些用来根据 RubyParser 兼容的 Sexps 轻松生成纯 Ruby 代码的方法。可在 Ruby 中轻松实现动态语言处理。 标签:ruby2ruby

    ruby源代码 ruby源代码 ruby源代码 ruby源代码2

    ruby源代码 ruby源代码 ruby源代码 ruby源代码2

    Ruby资源ruby-v3.1.1.zip

    Ruby是一种面向对象的、动态类型的编程语言,以其简洁、优雅的语法和强大的元编程能力而闻名。本资源“ruby-v3.1.1.zip”包含了Ruby的最新版本3.1.1,这是一个重要的里程碑,因为它引入了新特性、性能优化以及对旧...

    Ruby-TensorStream用Ruby重新实现TensorFlow

    **Ruby-TensorStream:用Ruby重现实现TensorFlow** Ruby-TensorStream是一个开源项目,旨在为Ruby开发者提供一个类似于Google TensorFlow的深度学习框架。它的核心目标是让Ruby程序员能够利用TensorFlow的强大功能...

    安装rvm,把ruby版本提升至3.0.0

    在IT行业中,管理和切换Ruby版本是一项常见的任务,特别是在开发环境中,不同的项目可能依赖于不同版本的Ruby。`RVM`(Ruby Version Manager)是解决这一问题的利器,它允许开发者在多个Ruby版本之间轻松切换。本文...

    ruby源代码 ruby源代码 ruby源代码 ruby源代码4

    ruby源代码 ruby源代码 ruby源代码 ruby源代码4

    ruby官方chm文档

    本套官方文档包含了关于Ruby核心库、标准库、语言特性和整体框架的详细信息,是学习和深入理解Ruby不可或缺的参考资料。 《ruby23-stdlib.chm》文档主要涵盖了Ruby的标准库(Standard Library)。Ruby标准库提供了...

    ruby语言帮助文当

    2. `ruby20-core.chm`:可能是关于Ruby 2.0核心库的文档,核心库包含了语言的基本结构和功能,如类、模块、对象、变量、控制结构等,是编写任何Ruby程序不可或缺的部分。 3. `ruby20.chm`:这个文件可能是整个Ruby ...

Global site tag (gtag.js) - Google Analytics