如果您想报告此常见问题解答中的错误或提出改进建议,请访问我们的 GitHub 存储库 并打开一个 issue 或 pull request。
语法
立即值和引用之间有什么区别?
本节或其中部分内容可能已过时或需要确认。
Fixnum、true、nil 和 false 被实现为立即值。对于立即值,变量保存的是对象本身,而不是对它们的引用。
不能为这些对象定义单例方法。两个具有相同值的 Fixnum 始终表示同一个对象实例,因此(例如)值为 1 的 Fixnum 的实例变量在系统中所有的 1 之间共享。这使得不可能仅为一个 1 定义单例方法。
nil 和 false 之间有什么区别?
首先是相似之处:nil 和 false 是在布尔上下文中评估为 false 的仅有的两个对象。(换句话说:它们是仅有的“假值”,所有其他对象都是“真值”。)
但是,nil 和 false 是不同类的实例(NilClass 和 FalseClass),并且在其他地方有不同的行为。
我们建议谓词方法(名称以问号结尾的方法)返回 true 或 false。其他需要指示失败的方法应返回 nil。
为什么空字符串不是 false?
问:空字符串 ("") 在条件表达式中返回 true!在 Perl 中,它是 false。
答:但是 Ruby 不是 Perl ;-)。很简单:在 Ruby 中,只有 nil 和 false 在条件上下文中为 false。
您可以使用 empty?,将字符串与 "" 进行比较,或将字符串的 size 或 length 与 0 进行比较,以确定字符串是否为空。
:name 是什么意思?
冒号后跟一个名称会生成一个 Symbol 对象,该对象与标识符一一对应。在程序执行期间,将为给定的名称或字符串创建相同的 Symbol 对象。也可以使用 "name".intern 或 "name".to_sym 创建符号。
Symbol 对象可以表示方法、变量等的标识符。某些方法,如 define_method、method_missing 或 trace_var,需要一个符号。其他方法,例如 attr_accessor、send 或 autoload,也接受字符串。
由于它们只被创建一次,因此 Symbol 通常用作哈希键。字符串哈希键会为每次使用创建一个新对象,从而导致一些内存开销。甚至还有用于符号哈希键的特殊语法
person_1 = { :name => "John", :age => 42 }
person_2 = { name: "Jane", age: 24 } # alternate syntax
符号也可以用作枚举值或为常量分配唯一值
status = :open # :closed, ...
NORTH = :NORTH
SOUTH = :SOUTH
如何访问符号的值?
要获取与符号对应的变量的值,您可以使用 symbol.to_s 或 "#{symbol}" 来获取变量的名称,然后在符号的作用域中评估该名称以获取变量的内容
a = "This is the content of `a'"
b = eval("#{:a}")
a.object_id == b.object_id # => true
您也可以使用
b = binding.local_variable_get(:a)
如果您的符号对应于方法的名称,则可以使用 send
class Demo
def hello
"Hello, world"
end
end
demo = Demo.new
demo.send(:hello)
或者您可以使用 Object#method 返回一个相应的 Method 对象,然后您可以调用该对象
m = demo.method(:hello) # => #<Method: Demo#hello>
m.call # => "Hello, world"
loop 是控制结构吗?
尽管 loop 看起来像一个控制结构,但它实际上是在 Kernel 中定义的方法。后面的块为局部变量引入了一个新的作用域。
Ruby 没有后测试循环
问:Ruby 没有 do { ... } while 构造,那么如何实现最后测试条件的循环?
Clemens Hintze 说:您可以使用 Ruby 的 begin ... end 和 while 或 until 语句修饰符的组合来实现相同的效果
i = 0
begin
puts "i = #{i}"
i += 1
end until i > 4
产生
i = 0
i = 1
i = 2
i = 3
i = 4
为什么我不能将哈希字面量传递给方法:p {}?
{} 被解析为块,而不是 Hash 构造函数。您可以通过使它是一个参数的事实明确地强制将 {} 视为表达式:p({})。
我无法让 def pos=(val) 工作!
我有以下代码,但我无法使用方法 pos = 1。
def pos=(val)
@pos = val
puts @pos
end
附加了 = 的方法必须使用显式接收器调用(如果没有接收器,您只是在分配给局部变量)。将其作为 self.pos = 1 调用。
'\1' 和 '\\1' 之间有什么区别?
它们具有相同的含义。在单引号字符串中,只有 \' 和 \\ 会被转换,其他组合保持不变。
但是,在双引号字符串中,"\1" 是字节 \001(一个八进制位模式),而 "\\1" 是包含反斜杠和字符 "1" 的两个字符的字符串。
.. 和 ... 之间有什么区别?
.. 在范围中包含右侧,... 不包含
(5..8).to_a # => [5, 6, 7, 8]
(5...8).to_a # => [5, 6, 7]
or 和 || 之间有什么区别?
问:p(nil || "Hello") 打印 "Hello",而 p(nil or "Hello") 给出解析错误。为什么?
答:or 的优先级非常低,p( (nil or "Hello") ) 将会起作用。
例如,or 的优先级也低于 = 的优先级,而 || 的优先级更高
foo = nil || "Hello" # parsed as: foo = (nil || "Hello")
foo # => "Hello"
# but perhaps surprisingly:
foo = nil or "Hello" # parsed as: (foo = nil) or "Hello"
foo # => nil
or(以及类似的 and)最好不要用于组合布尔表达式,而是用于控制流,如
do_something or raise "some error!"
当发生错误时,do_something 返回 false 或 nil。
Ruby 有函数指针吗?
由 Proc.new、proc 或 lambda 生成的 Proc 对象可以从变量中引用,因此可以说该变量是函数指针。您还可以使用 object.method 获取对特定对象实例中方法的引用。
load 和 require 之间有什么区别?
load 将加载并执行 Ruby 程序 (*.rb)。
require 也加载 Ruby 程序,但也会加载二进制 Ruby 扩展模块(共享库或 DLL)。此外,require 确保一个功能永远不会被多次加载。
Ruby 有异常处理吗?
Ruby 支持灵活的异常处理方案
begin
statements which may raise exceptions
rescue [exception class names]
statements when an exception occurred
rescue [exception class names]
statements when an exception occurred
ensure
statements that will always run
end
如果在 begin 子句中发生异常,则会执行具有匹配异常名称的 rescue 子句。无论是否发生异常,都会执行 ensure 子句。rescue 和 ensure 子句可以省略。
如果没有为 rescue 子句指定异常类,则默认使用 StandardError 异常,并且会捕获与 StandardError 存在 is_a? 关系的异常。
此表达式返回 begin 子句的值。
可以通过全局变量 $! 访问最近发生的异常(因此可以使用 $!.type 确定其类型)。