Ruby 边缘知识

行的开头用 =begin=end 括起来的部分也是注释

=begin
  This is comment
  with multiple lines
=end

变量前加上 *,表示 Ruby 会将未分配的值封装为数组赋值给该变量,也可以用在多重赋值上

a, b, *c = 1, 2, 3, 4, 5

p c # => [3, 4, 5]
ary = [1, [2, 3], 4]
a, b, c = ary

p a # => 1
p b # => [2, 3]
p c # => 4
ary = [1, [2, 3], 4]
a, (b1, b2), c = ary

p a  # => 1
p b1 # => 2
p b2 # => 3
p c  # => 4

对象的同一性

str1 = '1'
str2 = '1'

# detect value is equal
str1 == str2    # => true
str1.eql?(str2) # => true

# detect they are same object
str1.equal?(str2) # => false

# special case
1.0 == 1    # => true
1.0.eql?(1) # => false, use for more cautious programming

循环控制关键字

基本类继承关系

undef 删除方法

def hi
  puts "hi"
end

undef hi
undef :hi # => NameError (undefined method `hi' for class `Object')

赋值运算符

重新定义一元运算符

class Point
  attr_reader :x, :y

  def initialize(x = 0, y = 0)
    @x, @y = x, y
  end

  def inspect
    "(#{x}, #{y})"
  end

  def +@
    dup
  end

  def -@
    self.class.new(-x,-y)
  end

  def ~@
    self.class.new(y, x)
  end
end

point = Point.new(3, 6)
p +point # => (3, 6)
p -point # => (-3, -6)
p ~point # => (6, 3)

重新定义下标方法

class Point
  attr_writer :x, :y

  def [](index)
    case index
    when 0 then x
    when 1 then y
    else
      raise ArgumentError, "out of range `#{index}'"
    end
  end

  def []=(index, val)
    case index
    when 0
      self.x = val
    when 1
      self.y = val
    else
      raise ArgumentError, "out of range `#{index}'"
    end
  end
end

point = Point.new(3, 6)

p point[0] # => 3
point[0] = 1
p point[0] # => 1

异常类和语法补充

class Foo
  # something defined
rescue => ex
  # Exception handler
ensure
  # something must execute
end

位运算

def pb(i)
  # 使用 printf 的 %b 格式
  # 将证书的末尾 8 位用 2 进制表示
  printf("%08b\n", i & 0b11111111)
end

b = 0b11110000
pb(b)              # => 11110000
pb(~b)             # => 00001111 按位取饭
pb(b & 0b00010001) # => 00001000 按位与
pb(b | 0b00010001) # => 11110000 按位或
pb(b ^ 0b00010001) # => 11100001 按位异或
pb(b >> 3)         # => 00011110 位右移
pb(b << 3)         # => 10000000 位左移

计数

Here Document

print(<<"EOB")
1
2
EOB

Encoding.compatible?(str1, str2)

检查两个字符串的兼容性,兼容性是指两个字符串是否可以连接。可兼容则返回字符串连接后的编码,不可兼容则返回nil。

IO tty? 方法

通常标准输入、标准输出、标准错误输出都是与控制台关联的。但是将命令的输出重定向到文件,或者使用管道(pipe)将结果传递给其他程序时则与控制台没有关系。

# tty.rb
if $stdin.tty?
  print "Stdin is a TTY.\n"
else
  print "Stdin is not a TTY.\n"
end
ruby tty.rb # => Stdin is a TTY.

echo | ruby tty.rb     # => Stdin is not a TTY.
ruby tty.rb < data.txt # => Stdin is not a TTY.

IO binmode

新的 IO 对象默认是文本模式,使用 binmode 方法可将其变更为二进制模式

File.open("foo.txt", "w") do |io|
  io.binmode
  io.write "Hello, world.\n"
end

IO 缓冲

在向控制台输出的两种方式(标准输出与标注错误输出)中,标准错误输出完全不采用缓冲处理。

# test_buffering.rb

$stdout.print "out1 "
$stderr.print "err1 "
$stdout.print "out2 "
$stdout.print "out3 "
$stderr.print "err2\n"
$stdout.print "out4\n"

ruby test_buffering.rb
err1 err2
out1 out2 out3 out4

io.flush 强制输出缓冲,或者通过 io.sync = true,程序写入缓冲时 flush 方法就会被自动调用。