手记

Alex学Ruby[告诉你符号和范围的真相]


符号:

========你知道吗?

Ruby 里Symbol的实例就是一符号。

每个符号只有一个实例对象(类似于Fixnum)。

arr = ["foo","foo","foo",:bar,:bar,

:bar]

数组arr里的三个foo字符串分别是独立的三个对象,而那三个:bar是同一个字符对象的三个引用,所有有种说法,符号比字符串节省内存,可提高性能。

一个符合对应一个数字,存储为直接值。 可以使用to_i获取该数字。

>> :bar.to_i

=> 20041

>> :foo.to_i

=> 14585

========你知道吗?

一个把字符当作元值的例子:假设一个从网络中获取字符串的方法,可在发生异常时返回非字符串的值。

str = get_string

case str

when String

    ...

when :eof

    #end of file, socket colosed, whatever

when :error

    #I/O or network error

when :timeout

    # didnt get a reply

end

看起来比异常处理要好,

========你知道吗?

又一个例子:

>> sym1 = :@foo

=> :@foo

>> sym2 = :foo

=> :foo

>> instance_variable_set(sym1,"str1")

=> "str1"

>> instance_variable_set(sym2,"str1")

NameError: `foo' is not allowed as an instance variable name

如果用instance_variable_set必须指定准确的变量名。

========你知道吗?

>> :bar.to_s

=> "bar"

>> :bar.to_str

NoMethodError: undefined method `to_str' for :bar:Symbol

       from (irb):10

>> "bar".to_sym

=> :bar

to_s和to_sym方法来进行字符串和符号之间的转换。

========你知道吗?

list = words.map{|x| x.upcase}

我们可以在Symbol类里定义一个to_proc方法,

def to_proc

   proc{ |object,*args|  object.send(self,*args) }

end

有了这段代码我们可以重写:

list = words.map(:&upcase)

解释: map方法只接受代码块,通过使用&可传递proc,来代替显示的使用代码块。而这个时候&被应用于不是proc的对象,而传进来的本身是个符号对象(:&upcase),所以解释器自然而然的就会调用符号类的to_proc方法来得到一个proc。to_proc方法里的self引用的是对其调用了to_proc的符号。

-------------------------------------->>>>>>>>>>>>>>>>>>>>>

范围:

范围的起点和终点可以是任何Ruby对象,范围一般用于迭代。

========你知道吗?

>> r1 = "7".."9"

=> "7".."9"

>> r2 = "7".."10"

=> "7".."10"

>> r1.each{|x| puts x}

7

8

9

=> "7".."9"

>> r2.each{|x| puts x}

=> "7".."10"

两个看起来相似的范围对象,为什么迭代以后就有了不同的值呢 ?

原因在于第二个范围对象r2, 其终点是长度不同于r1终点的字符串。对r2进行迭代的时候,一般是以当当前值大于终点值时候结束循环,而字符串"7" 是大于"10"的,所以根本没有循环。用作终点的类,必须定义了有意义的succ方法。 不能对浮点数范围进行迭代,因为浮点数没有succ方法。

>> "7" > "10"

=> true

要随时注意使用的范围是否是字符串范围,否则会得到意想不到的结果:

>> r1 = "2".."5"

=> "2".."5"

>> s = "28"

=> "28"

>> r1.include?(s)

=> true

========你知道吗?

将范围用于条件句中,将被特别对待,. . 这种用法这个时候被称为flip-flop运算符。 有个例子,想输出一个ruby文件里=begin和=end之间的line。

loop do

  break if eof?

  line = gets

  puts  line  if  (line =~ /=begin/) .. (line =~ /=end/)

end

像这种根本不是范围,这个时候不能把它当范围来认知。

========补充

Ruby的遗憾是:

(1..5).to_a   #=> [1,2,3,4,5]

(1...5).to_a  #=> [1,2,3,4]

不能不包含其起点。。。

©著作权归作者所有:来自51CTO博客作者blackanger的原创作品,如需转载,请注明出处,否则将追究法律责任

职场Ruby休闲


0人推荐
随时随地看视频
慕课网APP