gpt4 book ai didi

ruby - 使用 include 检查数组中是否存在符号?

转载 作者:数据小太阳 更新时间:2023-10-29 07:45:36 24 4
gpt4 key购买 nike

Ruby Koans 的帮助下试用 Ruby .那里有以下测试:

def test_method_names_become_symbols
symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }
assert_equal __, symbols_as_strings.include?("test_method_names_become_symbols")
end

# THINK ABOUT IT:
#
# Why do we convert the list of symbols to strings and then compare
# against the string value rather than against symbols?

我试图在 irb 控制台中做同样的事情,但它为未定义的方法返回了 false。但后来我在一些 test.rb 文件中尝试了相同的操作,并且 true 返回到现有和不存在的方法。

示例代码:

def test_method
end
symbols = Symbol.all_symbols.map { |x| x }
puts symbols.include?(:test_method) # returns true in both cases
puts symbols.include?(:test_method_nonexistant) # returns false in irb, true if executed directly

问题是:为什么我们在这种情况下将符号转换为字符串,为什么在 irb 和普通文件中会有不同的结果?

谢谢!

最佳答案

让我们通过 irb 看到的测试代码的稍微修改版本并作为独立脚本:

def test_method;end
symbols = Symbol.all_symbols # This is already a "fixed" array, no need for map
puts symbols.include?(:test_method)
puts symbols.include?('test_method_nonexistent'.to_sym)
puts symbols.include?(:test_method_nonexistent)
eval 'puts symbols.include?(:really_not_there)'

当您在 irb 中尝试这样做时,每一行都将在下一行之前被解析和评估。当您点击第二行时,symbols 将包含 :test_method,因为 def test_method;end 已被评估。但是,当我们点击第 2 行时,:test_method_nonexistent 符号在任何地方都没有出现,因此第 4 行和第 5 行会显示“false”。当然,第 6 行会给我们另一个错误,因为 :really_not_thereeval 返回之前不存在。所以 irb 是这样说的:

true
false
false
false

如果您将其作为 Ruby 脚本运行,事情发生的顺序会略有不同。首先,Ruby 会将脚本解析为 Ruby VM 可以理解的内部格式,然后返回到第一行并开始执行脚本。脚本解析时,:test_method符号在解析完第一行后存在,:test_method_nonexistent符号在解析完第五行后存在;因此,在脚本运行之前,我们感兴趣的两个符号是已知的。当我们到达第六行时,Ruby 只看到了一个 eval 和一个字符串,但它还不知道 eval 导致了一个符号的存在。

现在我们有两个符号(:test_method:test_method_nonexistent)和一个简单的字符串,当输入到 eval 时,它将创建一个符号 (:really_not_there)。然后我们回到开头,VM 开始运行代码。当我们运行第 2 行并缓存我们的符号数组时,:test_method:test_method_nonexistent 都将存在并出现在 symbols 数组中,因为解析器创建了他们。所以第 3 行到第 5 行:

puts symbols.include?(:test_method)
puts symbols.include?('test_method_nonexistent'.to_sym)
puts symbols.include?(:test_method_nonexistent)

将打印“真”。然后我们点击第 6 行:

eval 'puts symbols.include?(:really_not_there)'

和“false”被打印是因为 :really_not_there 是由 eval 在运行时而不是在解析期间创建的。结果是 Ruby 说:

true
true
true
false

如果我们在末尾添加:

symbols = Symbol.all_symbols
puts symbols.include?('really_not_there'.to_sym)

然后我们将从 irb 和独立脚本中得到另一个“真”,因为 eval 将创建 :really_not_there我们将获取符号列表的新副本。

关于ruby - 使用 include 检查数组中是否存在符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8281118/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com