什么是符号,我们如何使用它们?

我不明白符号表是什么。 有人可以帮助我理解符号,从基础知识和彻底解释。

符号的最基本用法用短语概括: “符号是一个具有人类可读名称的常数整数” (作者Wei Lie Sho)。

如果在C中你键入:

#define USER 1 #define ADMIN 2 #define GUEST 3 [...] user.type = ADMIN; 

然后在ruby中你只需使用一个符号:

 user.type = :admin 

因此,ruby中的符号只是一些值,其中唯一重要的是名称 ,或换句话说: 符号的值是它的名称

符号和字符串之间的主要区别(因为这也是正确的代码: user.type = "admin" )是符号很快 。 符号和整数(在本例中使用)之间的主要区别在于符号对程序员来说很容易 ,而整数则不然。

其他Symbol属性对于它们的基本用法并不重要。


虽然有一些与符号相关的整数值(例如: .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 

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 

换句话说,比较两个符号只需要比较两个整数,而比较字符串可能需要比较一系列整数。 因此,比较符号比比较字符串更有效。

不同的符号每个都给出唯一的整数。 相同的符号被赋予相同的整数。

免责声明:以上描述中的任何实际错误不会以任何方式伤害您。

我假设你在谈论这样写的符号:something

符号是字符串,区别在于它们是“单身”(可以这么说)。

例如,

 a = "hello" b = "hello" 

a和b是内存中的不同对象,两者都具有相同的值。

但,

 a = :hello b = :hello 

a和b指向内存中的同一个对象,其中包含值“hello”

使用符号(在常量字符串上)的优点是它们只被分配一次(不熟悉Ruby中的符号表,但可能会进行这些分配)。 因此,您可以在多个位置使用它们,它们都指向相同的内存。

我看到你了解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更宽容。