简体   繁体   English

Ruby 中的符号

[英]Symbols in Ruby

I don't know if I understand what a symbol is.我不知道我是否理解符号是什么。 I read the following in different places:我在不同的地方阅读了以下内容:

  • Symbols are immutable, meaning that the content won't change after they are initialized.符号是不可变的,这意味着初始化后内容不会改变。 This means that the object can have many references to it since the content can't change.这意味着 object 可以有很多引用它,因为内容不能改变。
  • Use Symbols for identity and strings where content matters.在内容很重要的地方使用符号表示身份和字符串。
  • Symbol object are only instantiated once, and exists as long as the process runs.符号 object 只实例化一次,只要进程运行就存在。
  • About symbol table关于符号表

I do not understand these phrases.我不明白这些短语。 Last, I don't understand what a symbol object is.最后,我不明白 object 是什么符号。 Is :name a symbol object, or is :name just a reference to a symbol object somewhere else? :name是符号 object,还是:name只是对其他地方的符号 object 的引用?

This quote from the book ' Eloquent Ruby ' helped me understand symbols, there's a whole chapter in the book dealing with strings and symbols that is also very good.这本书的引用' Eloquent Ruby '帮助我理解了符号,书中有一整章处理字符串和符号也非常好。

The answer is that we tend to use strings of characters in our code for two rather dif- ferent purposes: The first, and most obvious, use for strings is to hold some data that we are processing. 答案是我们倾向于在我们的代码中使用字符串有两个相当不同的目的:第一个也是最明显的,字符串的用途是保存我们正在处理的一些数据。 Read in those Book objects from the database and you will very likely have your hands full of string data, things like the title of the book, the author's name, and the actual text. 从数据库中读入那些 Book 对象,你很可能会得到一堆字符串数据,比如书名、作者姓名和实际文本。

The second way that we use strings of characters is to represent things in our pro- grams, things like wanting to find all of the records in a table. 我们使用字符串的第二种方式是在我们的程序中表示事物,例如想要查找表中的所有记录。 The key thing about:all in our Book ActiveRecord example is that ActiveRecord can recognize it when it sees it—the code needs to know which records to return, and:all is the flag that says it should return every one. 关于:all 在我们的书 ActiveRecord 示例中的关键是 ActiveRecord 可以在看到它时识别它 - 代码需要知道要返回哪些记录,并且:all 是表示它应该返回每个记录的标志。 The nice thing about using something like:all for this kind of “stands for” duty is that it also makes sense to the humans: You are a lot more likely to recognize what:all means when you come across it than 0, or -1, or even (heaven forbid.) 0x29ef. 使用类似:all 来表示这种“代表”职责的好处是,它对人类来说也很有意义:当你遇到它时,你更有可能识别出 what:all 的含义,而不是 0,或者 - 1,甚至(天堂禁止)0x29ef。

These two uses for strings of characters—for regular data processing tasks on the one hand and for internal, symbolic, marker-type jobs on the other—make very dif- ferent demands on the objects. 字符串的这两种用途——一方面用于常规数据处理任务,另一方面用于内部、符号、标记类型的作业——对对象提出了非常不同的要求。 If you are processing data, you will want to have the whole range of string manipulation tools at your fingertips: You might want the first ten characters of the title, or you might want to get its length or see whether it matches some regular expression. 如果您正在处理数据,您将需要触手可及的所有字符串操作工具:您可能想要标题的前十个字符,或者您可能想要获取它的长度或查看它是否与某个正则表达式匹配。 On the other hand, if you are using some characters to stand for something in your code, you probably are not very interested in messing with the actual characters. 另一方面,如果您在代码中使用某些字符来代表某些东西,那么您可能对弄乱实际字符不太感兴趣。 Instead, in this second case you just need to know whether this thing is the flag that tells you to find all the records or just the first record. 相反,在第二种情况下,您只需要知道这个东西是告诉您查找所有记录还是仅查找第一条记录的标志。 Mainly, when you want some characters to stand for something, you simply need to know if this is the same as that, quickly and reliably. 主要是,当您希望某些字符代表某物时,您只需要快速可靠地知道这是否与那个相同。

Perhaps this IRB session can clear things up a little:也许这个 IRB session 可以澄清一点:

irb(main):001:0> "First".object_id
=> 23849064
irb(main):002:0> "First".object_id
=> 23842248
irb(main):003:0> "First".object_id
=> 23835432
irb(main):004:0> "First".object_id
=> 23828616
irb(main):005:0> :First.object_id
=> 301892
irb(main):006:0> :First.object_id
=> 301892
irb(main):007:0> :First.object_id
=> 301892
irb(main):008:0> :First.object_id
=> 301892
irb(main):009:0>

Imagine the object_id method as being similar to an object's address.object_id方法想象为类似于对象的地址。 As you can see, the "First" string has a different address each time ( meaning a new object gets created each time ), while the symbol doesn't change.如您所见,“First”字符串每次都有不同的地址(意味着每次都会创建一个新的 object),而符号不会改变。 Perhaps you could associate symbols with singletons ( as in the singleton pattern, not in a metaprogramming way ), for easier understanding.也许您可以将符号与单例相关联(如 singleton 模式,而不是元编程方式),以便于理解。

You could regard symbols as a sort of constants, but that don't contain an actual value.您可以将符号视为一种常量,但它不包含实际值。 In languages without symbols you might do something like this for convenience:在没有符号的语言中,为方便起见,您可能会执行以下操作:

const BLUE = 1
const GREEN = 2

my_color = GREEN

...


if (my_color == GREEN)

In Ruby you can use symbols for this:在 Ruby 中,您可以为此使用符号:

my_color = :green

...

if my_color == :green

It's more efficient since a symbol is just that, a symbol.它更有效,因为符号就是这样,一个符号。 It doesn't store a value or anything so you don't need to initialize them.它不存储值或任何东西,因此您无需初始化它们。 I'm not sure how symbols are handled in the Ruby interpreter, but I don't think that's relevant for any novice ruby programmer.我不确定 Ruby 解释器是如何处理符号的,但我认为这与任何新手 ruby 程序员无关。

A good guide can be found here: http://www.troubleshooters.com/codecorn/ruby/symbols.htm可以在这里找到一个很好的指南: http://www.troubleshooters.com/codecorn/ruby/symbols.htm

I think symbols are best explained via use-cases.我认为符号最好通过用例来解释。

For creating constants, they are more expressive than integers.对于创建常量,它们比整数更具表现力。

def rgb(color_symbol)
  return nil unless color_symbol.is_a? Symbol
  case color_symbol
  when :red;   { r: 255, g: 0, b: 0 }
  when :green; { r: 0, g: 255, b: 0 }
  when :blue;  { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_symbol= :red)

Is more readable than比可读性强

def rgb(color_number)
  return nil unless color_number.is_a? Fixnum
  case color_number
  when 1; { r: 255, g: 0, b: 0 }
  when 2; { r: 0, g: 255, b: 0 }
  when 3; { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_number= 2)

For comparisons in conditional statements, symbols are just compared via their unique address, so they are more efficient than strings, which are compared by length and then every character.对于条件语句中的比较,符号仅通过其唯一地址进行比较,因此它们比字符串更有效,字符串先按长度比较,然后按每个字符进行比较。

def rgb(color_string)
  return nil unless color_string.is_a? String
  case color_string
  when "red";   { r: 255, g: 0, b: 0 }
  when "green"; { r: 0, g: 255, b: 0 }
  when "blue";  { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_string= "blue")

This is going to be less efficient than using symbols.这将比使用符号效率低。

A Symbol instance is an ordered set of characters. Symbol实例是一组有序的字符。 A String instance is a container for characters, a place that can contain any sequence of characters. String实例是字符的容器,可以包含任何字符序列的地方。

This article can be also of interest http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/ as it helped me to understand how symbols differ from strings.这篇文章也很有趣http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/因为它帮助我理解了符号与字符串的不同之处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM