我的问题建立在这个问题的基础上:Ruby Koan:常量成为符号.我有以下代码:
in_ruby_version("mri") do
RubyConstant = "What is the sound of one hand clapping?"
def test_constants_become_symbols
all_symbols = Symbol.all_symbols
assert_equal __, all_symbols.include?(__)
end
end
Run Code Online (Sandbox Code Playgroud)
应该是正确的答案如下吗?
assert_equal true, all_symbols.include?("RubyConstant".to_sym)
Run Code Online (Sandbox Code Playgroud)
我知道我不应该这样做:
assert_equal true, all_symbols.include?(:RubyConstant)
Run Code Online (Sandbox Code Playgroud)
因为那时我可以把任何东西放在那里,它仍然是真的
assert_equal true, all_symbols.include?(:DoesNotMatter)
Run Code Online (Sandbox Code Playgroud)
提前道歉,问一个简单的"是或否"问题.我很好奇知道"正确"的答案是什么.我本来希望在上面提到的上一篇文章的评论中提出这个问题,但我不能不另外发表一篇文章.
Eya*_*lan 10
这是我得到的:
in_ruby_version("mri") do
RubyConstant = "What is the sound of one hand clapping?"
def test_constants_become_symbols
all_symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }
assert_equal true, all_symbols_as_strings.include?("RubyConstant")
end
end
Run Code Online (Sandbox Code Playgroud)
Symbol.all_symbols包含被引用的每个符号-变量名称,类名称,常量名称,实际符号。该变量实际包含的内容是实现定义的,但是在Ruby MRI中,此列表中已经包含许多符号。
irb(main):001:0> Constant = 42
=> 42
irb(main):002:0> Symbol.all_symbols
=> [:"", :"<IFUNC>", :"<CFUNC>", :respond_to?, ..., :irb_exit_org, :Constant]
Run Code Online (Sandbox Code Playgroud)
但是现在有一个陷阱。
Symbol.all_symbols.include?(:DoesNotMatter)
Run Code Online (Sandbox Code Playgroud)
在运行此代码之前,该代码:DoesNotMatter不存在all_symbols,但仍会以某种方式存在。好吧,实际上,当您使用符号文字时,会将其插入Symbol.all_symbols(除非已经存在)。因此,符号甚至在您致电之前就已经在这里.include?。
编辑:格雷戈里·布朗建议以下解决方法。它之所以有效,是因为在Ruby中Symbol.all_symbols出于某种原因分配了副本变量,而不是将引用复制到变量。
irb(main):001:0> symbols = Symbol.all_symbols; 1
=> 1
irb(main):002:0> symbols.include? :something
=> false
irb(main):003:0>
Run Code Online (Sandbox Code Playgroud)
注意:以下答案仅适用于irb等环境,其中Ruby代码是逐行执行的.在文件中执行代码时,Ruby会在执行任何操作之前扫描整个文件中的符号,因此以下详细信息不准确.我没有删除这个答案,因为它暴露了一个有趣的边缘情况,但请参阅@GlichMr的答案以更好地解释问题.
您可以安全地执行以下操作,因为Symbol.all_symbols返回符号数组的副本,而不是引用.
assert_equal true, all_symbols.include?(:RubyConstant)
Run Code Online (Sandbox Code Playgroud)
我认为这是koan的预期答案,这就是为什么all_symbols定义而不是Symbol.all_symbols直接调用.有关证据,请参阅以下内容:
>> X = 1
=> 1
>> all_symbols = Symbol.all_symbols; nil
=> nil
>> Y = 2
=> 2
>> all_symbols.include?(:X)
=> true
>> all_symbols.include?(:Y)
=> false
Run Code Online (Sandbox Code Playgroud)
使用String#to_sym可以Symbol.all_symbols直接进行这些调用,但不是解决这个问题所必需的.
| 归档时间: |
|
| 查看次数: |
1477 次 |
| 最近记录: |