- 7.1
instance_methods(true)
返回什么? - 7.2 为什么
rand
总是生成相同的随机数? - 7.3 怎样从0到51中选出5个不重复的随机数呢?
- 7.4
Fixnum
、Symbol
、true
、nil
和false
这些立即值与引用有什么不同? - 7.5
nil
和false
有什么不同? - 7.6 为什么读入文件并修改之后, 原文件依然没有变化?
- 7.7 怎样覆盖同名文件?
- 7.8 写文件后拷贝该文件,但所得副本并不完整,请问原因何在?
- 7.9 在管道中将字符串传给less后, 为什么看不到结果?
- 7.10 无法引用的
File
对象将会何去何从? - 7.11 怎样手动关闭文件?
- 7.12 如何按照更新时间的新旧顺序来排列文件?
- 7.13 如何获取文件中单词的出现频度?
- 7.14 为什么条件表达式中的空字符串表示true呢? 7.15 如何按照字典顺序来排列英文字符串数组?
- 7.16
"abcd"[0]
会返回什么? - 7.17 怎么把tab变成space?
- 7.18 如何对反斜线进行转义操作?
- 7.19
sub
和sub!
的区别在哪里? - 7.20 \Z匹配什么?
- 7.21 范围对象中的
..
和...
有什么不同? - 7.22 有函数指针吗?
- 7.23 线程和进程fork有何异同?
- 7.24 如何使用Marshal?
- 7.25 Ruby有异常处理语句吗?
- 7.26 如何使用
trap
? - 7.27 如何统计文件的行数?
- 7.28 怎样把数组转化为哈希表?
- 7.29 将字符串变为Array时可以使用%w(...),那么将字符串变为Hash时能不能如法炮制呢?
- 7.30 为何无法捕捉NameError异常呢?
- 7.31 为什么有succ却没有prev呢
7.1 instance_methods(true)
返回什么?<!---->
klass
.instance_methods只返回某klass
类(或模块)中所定义的实例方法, 而klass
.instance_methods(true)则会返回所有的实例方法, 包括从超类中继承来的实例方法。(但仅限于public方法)
private_instance_methods与protected_instance_methods的参数的意义相同。
7.2 为什么rand
总是生成相同的随机数?<!---->
在ruby 1.4.2以前的版本中, 每次执行程序时rand
都会生成相同的随机数。为了生成不同的随机数, 每次都必须使用srand
来给出不同的随机数种子。若不带参数地调用srand的话, 它将使用当时的时间作为种子, 因此可以产生出不同的随机数。
7.3 怎样从0到51中选出5个不重复的随机数呢?<!---->
下面的方法可以从0到n中选出m个随机数,并以数组的形式返回结果。
def sample(n, m) if m.zero? [] else s = sample(n-1, m-1) t = rand(n+1) s.concat s.include?(t) ? [n] : [t] end end
若不使用递归的话, 可以写成这样。
def sample(n, m) s = [] ((n-m)...n).each do |j| t = rand(j+2) s.concat s.include?(t) ? [j+1] : [t] end s end
7.4 Fixnum、Symbol、true
、nil
和false
这些立即值与引用有什么不同?<!---->
不能定义特殊方法。
另外, 表示同一个数字的Fixnum的实例通常都是相同的, 所以定义实例变量时, 它们的所指也是相同的。
7.5 nil
和false
有什么不同?<!---->
对nil.methods
- false.methods
和false.methods
- nil.methods
执行情况的差异就说明了nil和false所带方法的不同。
若某方法返回一个布尔值时,通常会返回true
或false
; 除此以外,方法通常返回值或nil
。
通常情况下, 带?
的方法会返回布尔值, 当然也有例外(在标准配置中只有nonzero?)。
7.6 为什么读入文件并修改之后, 原文件依然没有变化?<!---->
open("example", "r+").readlines.each_with_index{|l, i| l[0,0] = (i+1).to_s + ": "}
上面的代码并不能将行号添加到example
中。这是因为该代码并没有修改原文件, 而只是修改了readlines
读入的字符串而已。必须将修改后的内容写入文件才行。
io = open("example", "r+") ary = io.readlines ary.each_with_index{|l, i| l[0,0] = (i+1).to_s + ": "} io.rewind io.print ary io.close
此时因为文件增大了, 所以没有出现什么问题. 如果文件变小的话,就必须将下列代码
io.flush io.truncate(io.pos)
嵌入到io.close之前才行.
7.7 怎样覆盖同名文件?<!---->
使用命令行选项-i
或者将内部变量$-i
设为""之后, 就可以覆盖同名文件了。
您可以使用下列代码。
$ ruby -i -ne 'print "#$.: #$_"' example
若想保留原来的文件时, 可以-i.bak
这样。
7.8 写文件后拷贝该文件,但所得副本并不完整,请问原因何在?<!---->
open('file', 'w').print "This is a file.\n" system 'cp file copy'
上述代码之所以出错,是因为拷贝文件时有一部分内容尚未被flush进file
中所致。因此,请先close
然后再进行拷贝。
f = open('file', 'w') f.print "This is a file.\n" f.close system "cp file copy"
7.9 在管道中将字符串传给less后, 为什么看不到结果?<!---->
f = open '|less', 'w' f.print "abc\n"
上述代码会立刻结束,您无法看到less的显示结果。添加一个close
,以便等待less
完成显示。
f = open '|less', 'w' f.print "abc\n" f.close
第一行也可以写成f = IO.popen 'less', 'w'
。
7.10 无法引用的File对象将会何去何从?
open("file").read
中的File是无法引用的, 它会被后来的垃圾回收器所close
和销毁.
7.11 怎样手动关闭文件?
GC会自动关闭不再使用的File对象. 若您想自己关闭文件的话, 可以从下面4种方法中任选其一(按照代码长度排列)。
-
File.foreach('filename') {|line| print line }
-
File.readlines('filename').each {|line| print line }
-
File.open('filename') {|f| f.each {|line| print line } }
-
begin f = File.open('filename') f.each {|line| print line } ensure f.close if f end
7.12 如何按照更新时间的新旧顺序来排列文件?<!---->
Dir.glob("*").collect{|f| [File.mtime(f), f] }. sort{|a,b| b[0]<=>a[0] }.collect{|e| e[1] }
上述代码将会按照更新时间的新旧顺序来排列当前目录中(除了"."、".."以外)的文件, 并以数组的形式返回结果. 若想按照相反顺序来排序的话, 就可以去掉sort后面的块。
Dir.glob("*").sort{|a,b| File.mtime(b)<=>File.mtime(a)}
尽管这样可以完成排序, 但是每次都要访问文件来获取更新时间, 因而排序过程较慢。
为解决这个问题, 可以先生成一个对象, 它负责将每个文件的更新时间存入高速缓存, 这样就可以提高处理速度。
cache = {} def cache.mtime(x) self[x] ||= File.mtime(x) end Dir.glob("*").sort{|a,b| cache.mtime(b) <=> cache.mtime(a)} cache = nil
另外,在ruby 1.7中提供了Enumerable#sort_by方法, 使用它可以轻松完成上述任务。
Dir.glob("*").sort_by {|f| File.mtime(f)}.reverse
7.13 如何获取文件中单词的出现频度?<!---->
将哈希表的默认值设为0之后, 可以这样处理。
freq = Hash.new(0) open("file").read.scan(/\w+/){|w| freq[w] += 1} freq.keys.sort.each {|k| print k, "--", freq[k], "\n"}
7.14 为什么条件表达式中的空字符串表示true呢?7.15 如何按照字典顺序来排列英文字符串数组?<!---->
在Ruby中,只有nil
和false
表示假, 其他的都表示真。若想判断某字符串是否为空时, 可以将它与""作比较,或者使用empty?
, 或者将其length
与0
作比较 即可得出结果。
您可以这样排序
ary.collect{|f| [f.downcase, f]}.sort.collect{|e| e[1]}
若downcase
形式相等时, 则按照原来字符串来排序。
7.16 "abcd"[0]
会返回什么?<!---->
它将返回字符a的代码97(Fixnum)。若想验证它与a是否一致时,可以使用?a进行比较。
7.17 怎么把tab变成space?<!---->
常用方法如下。
# 非破坏性的方法 def expand_tab( str ) str.gsub(/([^\t]{8})|([^\t]*)\t/n) { [$+].pack("A8") } end # 破坏性的方法 def expand_tab!( str ) 1 while str.sub!(/(^[^\t]*)\t(\t*)/) { $1 + ' ' * (8-$1.size%8+8*$2.size) } end # 破坏性的方法 (2) def expand_tab!( str ) 1 while str.sub!(/\t(\t*)/) {' ' * (8-$~.begin(0)%8+8*$1.size) } end
7.18 如何对反斜线进行转义操作?<!---->
在正则表达式中, Regexp.quote('\\')
就可以实现转义。
若使用gsub
的话, 在gsub(/\\/, '\\\\')
中,进行句法分析时会将替换字符串变为'\\', 而实际替换还会将其解释成'\', 所以必须写成gsub(/\\/, '\\\\\\')
才行。若使用\&来表示匹配字符串的话, 则可以写成gsub(/\\/,'\&\&')
。
另外, 若使用形如gsub(/\\/){'\\\\'}
的块的话, 就只会进行一次转义, 因此可以得到预期的结果。
7.19 sub
和sub!
的区别在哪里?<!---->
sub
不会改变被调的状态。首先,它会拷贝字符串, 然后在副本中进行替换操作,并返回结果(若没有必要替换时,就直接返回副本)。
而sub!
则会改变被调本身。若没有进行替换的必要时, 将返回nil
。
像sub!
这种会修改被调本身的方法叫做破坏性的方法。在Ruby中, 若同时存在同名的破坏性方法和非破坏性方法时, 通常在破坏性方法名后添加!。
def foo(str) str = str.sub(/foo/, "baz") end obj = "foo" foo(obj) print obj #=> "foo" def foo(str) str = str.sub!(/foo/, "baz") end foo(obj) print obj #=> "baz"
像sub!
这样的破坏性的方法可能会带来非预期的效果, 请慎用。
7.20 \Z匹配什么?<!---->
当字符串末尾字符不是\n时,\Z匹配于字符串的末尾字符;当字符串的末尾字符是\n时,它匹配于换行之前的部分。
若想让它一直匹配于末尾字符,而不理会\n的问题时,应该使用\z。
7.21 范围对象中的..
和...
有什么不同?<!---->
..
包含终点,而...
不包含终点。
7.22 有函数指针吗?<!---->
若使用Proc.new
、proc
、lambda
生成了Proc对象的话,就可以将其用作函数指针。
另外,Method和UnboundMethod对象也很类似于函数指针。
7.23 线程和进程fork有何异同?<!---->
线程和进程fork分别具有以下特点:
- 进程间不能共享内存
- 线程和进程的切换都是不定时的
- Ruby线程可运行于任何OS
- 若Ruby线程发生阻塞的话,整个都会停顿下来(non preemptive)
- Ruby线程不会引发系统颠簸(thrashing)(*)
*系统颠簸是指,当进程或线程过多时,因处理它们的切换问题而消耗了过多的系统时间,所导致的系统无效。
通常不应该混用进程fork和线程。
因为Ruby线程采用分时机制,所以使用进程后并不会加快处理速度。由于Ruby线程是用户线程,因此无法享受多处理机的好处。
7.24 如何使用Marshal?<!---->
它可以将对象转变为字节串(即serialize)。您可以将对象存入文件,以后再将其还原,或者通过网络把它发送出去。例如,您可以这样把obj对象转为字节串
Marshal.dump(obj)
该方法返回字符串,因此可以将其存入文件。
File.open('filename', 'w') {|f| f.write Marshal.dump(obj) }
因为经常需要进行上述操作,所以Ruby提供了下列简便方法。
Marshal.dump(obj, io)
io表示可写入的IO对象。另外使用上述方法处理较大的对象时,就省去了生成巨大字符串的麻烦。
另一方面,您可以像下面这样来还原对象。首先是使用字符串进行还原的例子。
obj = Marshal.load(str)
下面的是直接使用IO对象进行还原。
obj = Marshal.load(io)
7.25 Ruby有异常处理语句吗?<!---->
有。通常使用下列语句。
begin (发生异常之前所处理的事务) rescue (异常类) (发生异常时的处理) else (没有异常时的处理) ensure (必须处理的事务) end
在begin
语句中,若发生异常就会执行rescue
部分。若没有异常就执行else
部分。另外,不管有没有异常,都必须执行ensure
部分。rescue
,else
和ensure
部分都是可以省略的。若rescue
后面没有给出异常类,就使用StandardError作为其默认值。此时将捕捉StandardError的子类。
该语句的值取决于执行ensure
部分之前的值。
另外,您可以使用全局变量$!
来获得最后发生的异常,使用$!.class
来了解该异常的种类。
7.26 如何使用trap
?<!---->
下面的代码在捕捉到SIGPIPE信号时会执行块的内容(随即引发异常)。
trap("PIPE") {raise "SIGPIPE"}
7.27 如何统计文件的行数?<!---->
若假定文件末尾也有个换行符的话,下面的方法可能是最简单的。
open("filename").read.count("\n")
7.28 怎样把数组转化为哈希表?<!---->
您可以这样把数组array转化为哈希表
h = Hash[*array]
此时array中的奇数元素将成为哈希表h的键,而偶数元素将成为相对应的值。数组array中的元素个数必须是偶数。
array = [1,2,3,4] h = Hash[*array] p h => {1=>2, 3=>4}
数组array前面的"*"表示展开参数。
7.29 将字符串变为Array时可以使用%w(...),那么将字符串变为Hash时能不能如法炮制呢?<!---->
您不能像生成Array那样来直接生成Hash,但您可以这样
p h = Hash[*%w(1 foo 2 bar)] => {"1"=>"foo", "2"=>"bar"}
先生成Array,然后将其转化为Hash。(但此时哈希表的键和值都被限定为字符串)
7.30 为何无法捕捉NameError异常呢?<!---->
在1.4以前的版本中,下列代码中的rescue部分都可以正常运行,可是到了1.6版本就不行了。
begin foo rescue puts "TRAP : #$!" end -:2: undefined local variable or method `foo' for #<object:0x401bece0> (NameError) ruby 1.6.7 (2002-03-20) [i586-linux]
这是因为NameError异常类不再是StandardError的子类所致(若不指定异常类时,rescue将只负责捕捉StandardError
旗下的异常类)。此时,必须显式地指定NameError才行。
begin foo rescue NameError puts "**TRAP** : #$!" end ruby 1.6.7 (2002-03-20) [i586-linux] **TRAP** : undefined local variable or method `foo' for #<object:0x401bece0>
可是到了1.7版本时,NameError类又重新成为StandardError的子类。请您参考异常类中的类层次构造来了解默认情况下所能捕捉的异常的范围。
7.31 为什么有succ却没有prev呢?<!---->
虽然定义Integer#prev
并不困难,但却没有succ
实用。
另一方面,定义String#prev
则比较困难。例如
'09'.succ == '9'.succ #=> true
因为有时succ前和后的字符串并不是一一对应的,所以str.prev.succ == str.succ.prev
未必成立。
相关推荐
Ruby-DingTalkBot是针对阿里钉钉自定义机器人的一款Ruby编程语言实现的库,它使得开发者可以方便地在Ruby环境中与钉钉机器人进行交互,发送各种类型的消息到钉钉群或者个人工作台,从而实现自动化通知、信息推送等...
Ruby-Logging库是一个在Ruby编程语言中广泛使用的日志处理工具,它借鉴了Java的log4j库的设计理念,提供了一种灵活、可扩展的方式来记录应用程序的运行信息。这个库的核心目标是帮助开发者轻松地控制日志输出的级别...
通过`addressable-master`这个压缩包文件,你可以获取到`Addressable`库的源代码,学习其内部实现原理,或者根据项目需求对其进行定制。在Ruby开发中,`Addressable`库是一个强大的工具,可以极大地提升URI处理的...
Ruby-Fog是一个强大的Ruby库,专门用于与各种云服务提供商进行交互。这个库的主要目标是为开发者提供一个统一的、简化的接口,使得在不同云平台之间切换变得更加便捷。Fog支持众多的服务,包括计算、存储、数据库、...
Ruby-Prawn是一个强大的开源库,专门用于在Ruby环境中创建PDF文档。它以其高效、灵活性和易用性而闻名,使得开发者能够快速地生成高质量的PDF文件。Prawn库的出现填补了Ruby在PDF生成领域的空白,为开发者提供了一个...
- **学习开源库**: 对于初学者或新接触的开源库,`TraceLocation` 可以帮助逐步了解其内部工作原理。 3. **工作原理** Ruby的`TracePoint` 类是`TraceLocation` 的核心,它允许我们订阅并处理各种事件,如方法...
Parallel Ruby库通过内部的同步机制尽可能地减少了这些问题,但开发者仍需谨慎设计代码,避免不必要的数据交互。 总之,Parallel Ruby库为Ruby开发者提供了一种高效、易用的并行处理解决方案,使得在Ruby中实现高...
- **MRI内部机制**:MRI(Matz's Ruby Interpreter)是Ruby的标准实现,它通过GIL保证了内存安全性和数据一致性。 - **特殊情况:阻塞I/O操作**:当线程执行阻塞I/O操作时,GIL会被释放,允许其他线程执行。 #### ...
Ruby的启动 命令行选项 关于解释器行 环境变量 Ruby 语言样式 对象 类 执行 结束时的相关处理 线程 安全模型 正则表达式 Ruby的语法 字句构造 程序 变量和常数 字面值 操作符表达式 控制结构/...
Ruby的Refile库是用于构建Web应用程序中的文件上传功能的一个高效且灵活的解决方案。它旨在提供简洁的API,同时保持高度可定制性,使得开发者在处理用户上传的文件时能够轻松应对各种需求。Refile的核心理念是将文件...
总结来说,该主题涉及了使用Visual Studio 2010这一专业开发工具来编译Ruby语言的源代码,这对于开发者来说是一个有价值的技能,特别是对于那些希望深入了解Ruby内部工作原理或者需要优化性能的场景。通过学习和实践...
Ruby-Yard是一款专门为Ruby语言设计的强大文档工具,旨在帮助开发者更高效、更规范地生成和管理他们的代码...通过探索"lsegal-yard-0320b89",开发者可以进一步了解Yard的内部机制和如何利用它来优化自己的Ruby项目。
3. `ruby_core_source-0.1.5.gem`:这个组件提供了对Ruby内核源码的访问,使得调试器可以获取到关于Ruby内部操作的详细信息。这对于深入理解Ruby引擎的工作原理,以及调试涉及到Ruby核心部分的问题非常有帮助。 ...
Ruby-Savon是Ruby编程语言中的一个强大的SOAP(Simple Object Access Protocol)客户端库,它使得在Ruby中与SOAP服务交互变得简单而高效。SOAP是一种基于XML的协议,用于在不同系统之间交换结构化和类型化的数据,常...
在实际应用中,Mechanize通常与其他Ruby库结合使用,如Nokogiri进行更精细的HTML解析,或者CSV、YAML等库来存储和处理抓取的数据。此外,还可以使用如Selenium这样的库进行更高级的浏览器控制,以处理JavaScript渲染...
1. **性能优化**:Fast JSON API通过精心优化的代码和内部缓存机制,实现了比其他序列化库更快的速度,减少了不必要的内存开销和CPU使用率。 2. **轻量级**:Fast JSON API的设计目标是保持简洁,仅关注JSON:API的...
通过命令行参数,我们可以传递参数给Ruby脚本并在脚本内部处理。标准输入/输出则允许脚本与用户或其它程序进行数据交换。文件操作允许脚本读写文件,实现数据持久化。网络通信则支持HTTP、TCP/IP等协议,使得脚本...
在`rest-client-master`压缩包中,可能包含的是RESTClient库的源代码,如果你想要了解其内部实现或者进行二次开发,可以查看里面的文件。通常,这样的源代码包会有`lib/restclient`目录,其中包含了核心的类和模块,...
2. **事件驱动**:Puma利用Ruby的事件库,如libuv或eventmachine,实现非阻塞I/O,使服务器能够高效地处理大量并发连接。 3. **热重启**:Puma支持热重启功能,这意味着在不中断服务的情况下可以更新应用程序代码。...
Faraday是Ruby编程语言中的一款轻量级且高度可扩展的HTTP客户端库。它由Michael Hartl创建,设计目标是提供一个简洁而统一的接口,用于处理各种HTTP客户端后端,如Net::HTTP、Excon、HTTPClient等。这个库的名字...