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

发布于 2024-11-24 19:19:04 字数 41 浏览 2 评论 0原文

我不明白符号表是什么。有人可以帮助我从基础开始理解符号并彻底解释吗?

I do not understand what a symbol table is. Can someone help me understand symbols, from the very basics and explain thoroughly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等风来 2024-12-01 19:19:04

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

如果在 C 中你输入:

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

那么在 ruby​​ 中你只需使用一个符号:

user.type = :admin

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

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

其他符号属性对于其基本用途并不重要。


虽然有一些与符号关联的整数值(例如:.object_id),但您不应依赖它。在程序的每次运行中,给定符号的整数值可能不同。但是,当您的程序运行时,同一符号的每个(我们这样称呼它)“实例”将具有相同的整数值。

与整数常量(如 C 示例中的那样)不同,在 Ruby 1.8 中符号无法排序-它们不知道一个符号是否大于另一个符号。

因此,您可以像匹配整数一样快速地匹配符号(为了相等),但是您不能在 Ruby 1.8 中直接对符号进行排序。当然,您可以对符号的字符串等价物进行排序:

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 中有效地使用符号。


请注意,在 Ruby 1.9 符号包括 Comparable,因此您可以执行以下操作:

p :yay if :foo > :bar 

The most basic usage of Symbols is well summarized with phrase: "A Symbol is a constant integer with human readable name" (by Wei Lie Sho).

If in C you type this:

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

then in ruby you just use a Symbol:

user.type = :admin

So, a Symbol in ruby is just some value, in which the only important thing is the name, or put in other words: the value of the Symbol is its name.

The main difference between Symbols and Strings (because this is also correct code: user.type = "admin") is that Symbols are fast. The main difference between Symbols and integers (used as in this example) is that the Symbols are easily readable for the programmer, while integers are not.

Other Symbol properties are not crucial for their basic usage.


While there is some integer value associated with Symbols (for example: .object_id), you should not rely on it. In each run of your program the integer value of a given Symbol may be different. However, while your program runs, each (let's call it so) "instance" of the same Symbol will have the same integer value.

Unlike the integer constants (as in the C example) the Symbols cannot be sorted in Ruby 1.8 - they do not know whether one is greater than another.

So, you can match Symbols (for equality) as quick as integers are matched, but you cannot sort Symbols directly in Ruby 1.8. Of course, you can sort the String equivalents of Symbols:

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]

One of the important properties of Symbols is that once a Symbol is encountered in the program (typed in the source code or created 'on-the-fly'), its value is stored until the end of the program, and is not garbage-collected. That's the "Symbol-table" you mentioned.

If you create a lot of unique Symbols in your program (I talk about millions), then it is possible that your program will run out of memory.

So, a rule of thumb is: "Never convert any user supplied value to Symbols".

# A Rails-like example:
user.role = params["role"].to_sym # DANGEROUS!

I believe this set of information may be sufficient for using Symbols efficiently in Ruby.


Note that in Ruby 1.9 Symbols include Comparable, and so you can do things like

p :yay if :foo > :bar 
你的他你的她 2024-12-01 19:19:04

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

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

不同的符号各自被赋予唯一的整数。相同的符号赋予相同的整数。

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

A ruby symbol is a pointer to a place in memory where there is a constant string. And all identical symbols point to the same place in memory.

A pointer is just an integer representing an address in memory, where addresses in memory are much like the addresses of houses in a city. And each address is unique. In effect, ruby transforms each symbol into a single integer: the address of a constant string in memory.

In order for ruby to compare two strings, ruby starts with the first letter of each string and compares their ascii codes. If they are the same, then ruby moves on to the second letter of each string to compare their ascii codes--until ruby finds a difference in the ascii codes or the end of one of the strings is reached. For instance, with these two strings:

"hello_world_goodbye_mars"
"hello_world_goodbye_max"

ruby has to compare each letter of the two strings until if finds a difference at 'r' and 'x' in order to tell that the strings are not the same.

On the other hand, ruby only has to make one comparison when comparing symbols--no matter how long the symbol is. Because a symbol is effectively just a single integer, in order for ruby to tell whether the following two symbols are different:

:hello_world_goodbye_mars
:hello_world_goodbye_max

ruby only has to do one comparison: the integer representing the first symbol v. the integer representing the second symbol; and the comparison becomes something like:

if 245678 == 345789
  #then the symbols are the same
else
  #the symbols are not the same
end

In other words, comparing two symbols only requires comparing two integers, while comparing strings can require comparing a series of integers. As a result, comparing symbols is more efficient than comparing strings.

Symbols that are different are each given unique integers. Identical symbols are given identical integers.

Disclaimer: any factual errors with the above description will not harm you in any way.

在风中等你 2024-12-01 19:19:04

我假设您正在谈论像这样编写的符号 :something

符号是字符串,不同之处在于它们是“单例”(可以这么说)。

例如,

a = "hello"
b = "hello"

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

但是,

a = :hello
b = :hello

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

使用符号(相对于常量字符串)的优点是它们仅分配一次(不熟悉Ruby中的符号表,但它可能这些分配是在哪里进行的)。因此,您可以在多个地方使用它们,并且它们都指向相同的内存。

I am assuming you are talking about symbols which are written like this :something.

Symbols are strings, with the difference that they are "singleton" (so to speak).

For example,

a = "hello"
b = "hello"

a and b are different objects in memory, both of which have the same value.

But,

a = :hello
b = :hello

a and b point to the same object in memory, which contains the value "hello"

The advantage of using symbols (over constant strings) is that they are allocated only once (not familiar with a symbol table in Ruby, but it might where these allocations are made). So, you can use them in multiple places and they are all pointing to the same memory.

留蓝 2024-12-01 19:19:04

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

I see you know Java. Well, the nearest thing to a Java string in Ruby is a symbol: you can't change them, and strings with the same content are actually the same object.

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

Compare this to Ruby strings, which you can change -- more like a Stringbuf(?) object in Java? (Sorry, my Java is very rusty indeed).

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]

So symbols are the best thing to use as a key to a Hash; or anywhere where you need a string that won't change, because they are faster than strings. So long as you remember that they can't change, you can use them in exactly the same way as a string. Ruby is more forgiving than Java.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文