我不明白符号表是什么。有人可以从基础知识中帮助我理解符号并彻底解释。
答案 0 :(得分:12)
符号的最基本用法总结如下:“符号是一个具有人类可读名称的常量整数”(作者Wei Lie Sho)。
如果在C中你键入:
#define USER 1
#define ADMIN 2
#define GUEST 3
[...]
user.type = ADMIN;
然后在红宝石中你只需使用一个符号:
user.type = :admin
所以,ruby中的符号只是一些值,其中唯一重要的是名称,换句话说:符号的值是它的名字
符号和字符串之间的主要区别(因为这也是正确的代码:user.type = "admin"
)是符号快速。符号和整数(在本例中使用)之间的主要区别在于,符号对于程序员来说很容易可读,而整数则不是。
其他符号属性对于它们的基本用法并不重要。
虽然有一些与符号关联的整数值(例如:.object_id
),但您不应该依赖它。在程序的每次运行中,给定Symbol的整数值可能不同。但是,当你的程序运行时,每个(让我们称它为)同一个符号的“实例”将具有相同的整数值。
与整数常量(如C示例中)不同,符号无法在Ruby 1.8中排序 - 他们不知道一个是否大于另一个。
因此,您可以像匹配整数一样快速匹配符号(用于相等),但不能直接在Ruby 1.8 中对符号进行排序。当然,您可以对符号的String等效项进行排序:
if user.type == :admin # OK
if user.type > :guest # will throw an exception.
[:two, :one].sort # will throw an exception
[:two, :one].sort_by {|n| n.to_s} # => [:one, :two]
符号的一个重要属性是,一旦在程序中遇到符号(在源代码中键入或在“即时”中创建),其值将被存储到程序结束,并且不是垃圾收集。这就是你提到的“符号表”。
如果你在程序中创建了许多独特的符号(我谈论数百万),那么你的程序可能会耗尽内存。
因此,经验法则是:“永远不要将任何用户提供的值转换为符号”。
# A Rails-like example:
user.role = params["role"].to_sym # DANGEROUS!
我相信这组信息可能足以在Ruby中有效地使用Symbols。
请注意,Ruby 1.9中的 符号包含Comparable
,因此您可以执行以下操作:
p :yay if :foo > :bar
答案 1 :(得分:2)
ruby符号是指向内存中存在常量字符串的位置的指针。所有相同的符号都指向内存中的相同位置。
指针只是一个表示内存中地址的整数,其中内存中的地址非常类似于城市中房屋的地址。每个地址都是独一无二的。实际上,ruby会将每个符号转换为一个整数:内存中常量字符串的地址。
为了让ruby比较两个字符串,ruby以每个字符串的第一个字母开头并比较它们的ascii代码。如果它们是相同的,则ruby移动到每个字符串的第二个字母以比较它们的ascii代码 - 直到ruby在ascii代码中找到差异或者到达其中一个字符串的末尾。例如,使用这两个字符串:
"hello_world_goodbye_mars"
"hello_world_goodbye_max"
ruby必须比较两个字符串中的每个字母,直到在“r”和“x”处找到差异才能告诉字符串不相同。
另一方面,ruby只需在比较符号时进行一次比较 - 无论符号有多长。因为符号实际上只是一个整数,所以为了让ruby判断以下两个符号是否不同:
:hello_world_goodbye_mars
:hello_world_goodbye_max
ruby只需进行一次比较:表示第一个符号的整数v表示第二个符号的整数;并且比较变得像:
if 245678 == 345789
#then the symbols are the same
else
#the symbols are not the same
end
换句话说,比较两个符号只需要比较两个整数,而比较字符串可能需要比较一系列整数。因此,比较符号比比较字符串更有效。
不同的符号每个都有唯一的整数。相同的符号被赋予相同的整数。
免责声明:上述说明中的任何实际错误都不会对您造成任何伤害。
答案 2 :(得分:0)
我假设你在谈论像:something
这样写的符号。
符号是字符串,区别在于它们是“单身”(可以这么说)。
例如,
a = "hello"
b = "hello"
a和b是内存中的不同对象,两者都具有相同的值。
但是,
a = :hello
b = :hello
a和b指向内存中的同一个对象,其中包含值“hello”
使用符号(在常量字符串上)的优点是它们只被分配一次(不熟悉Ruby中的符号表,但可能在这些分配的位置)。因此,您可以在多个位置使用它们,它们都指向相同的内存。
答案 3 :(得分:0)
我看到你了解Java。嗯,Ruby中最接近Java字符串的是符号:您无法更改它们,具有相同内容的字符串实际上是同一个对象。
irb(main):001:0> a = :firstthing
=> :firstthing
irb(main):002:0> b = :firstthing
=> :firstthing
irb(main):004:0> p a.object_id
467368
=> 467368
irb(main):005:0> p b.object_id
467368
=> 467368
将此与您可以更改的Ruby字符串进行比较 - 更像是Java中的Stringbuf(?)对象? (对不起,我的Java确实非常生疏。)
irb(main):006:0> a = "secondthing"
=> "secondthing"
irb(main):007:0> b = "secondthing"
=> "secondthing"
irb(main):009:0> p a.object_id, b.object_id
8746200
8760220
=> [8746200, 8760220]
因此,符号是用作哈希键的最佳选择;或者你需要一个不会改变的字符串的任何地方,因为它们比字符串更快。只要你记得它们无法改变,你就可以使用它们与字符串完全相同的方式。 Ruby比Java更宽容。