【问题标题】:Are Ruby symbols the equivalent of PHP constants?Ruby 符号是否等同于 PHP 常量?
【发布时间】:2018-04-13 08:42:53
【问题描述】:

似乎在内存方面可能存在差异,但除此之外,它们看起来非常相似。我应该注意哪些差异?

【问题讨论】:

  • PHP 常量不能引用任何东西吗?
  • @sawa - 不,他们不能,例如你不能把一个对象放在一个常量中。直到最近你只能把原语放在那里(如果我记得 PHP7 现在允许数组作为常量)。那就是说我不知道​​Ruby是如何做到的。但是说anything 是一种广泛的方式...... :-p
  • 我明白了。但似乎 PHP 仍然允许更多的东西被称为常量。
  • 有用户定义的全局常量define('Constant', $value ) 和类常量class foo{ const Constant = 1; } 并使用foo:Constant; 访问您也可以使用$var = 'foo'; 然后$var::Constant; 但这可能会让您大吃一惊。跨度>
  • class constantsdefined constants 的任何一种情况下,您都无法在运行时更改该值。这就是为什么它们是常数。类常量很有用,因为它们不会弄乱全局空间,并且比全局常量更容易定位。

标签: php ruby symbols


【解决方案1】:

ruby 中的符号和 PHP 中的常量并不完全等同。

大多数 ruby​​ 实现都保留了解释器内部的符号表。符号表存储在整个程序中使用的标识符,如所述表中的方法名、类名等。所述名称的查找是基于所述名称在符号表中的整数位置来执行的。

符号本身就是对象,符号名称和符号对象是一一对应的。所以当你有例如def hello ... 并在程序的某处调用hello 方法,这指的是与您引用:hello 完全相同的对象。符号表基本上是一种避免在整个程序中引用常用名称时进行大量字符串比较的方法。

为了说明,请考虑以下代码:

class A
  def hello
    puts "the method name is #{__method__}"
    puts "the class of the method name is #{__method__.class}"
    puts "the object ID of the name hello is #{__method__.__id__}"
  end
end

A.new.hello
puts "the object id of :hello is #{:hello.__id__}"

这个输出:

$ the method name is hello
the class of the method name is Symbol
the object ID of the name hello is 898268
the object id of :hello is 898268

所以,方法名 'hello' 和符号 :hello 指的是同一个对象。以这种方式存储符号减少了对象分配 - 正如您所暗示的那样 - 并且通过扩展可以更快地查找程序中的常用名称。

此外,您不能为符号赋值。例如,:hello = "blah" 将不起作用。因为 :hello 根据内部符号表有一个非常具体的值。这是 ruby​​ 符号和 PHP 常量之间的另一个明显区别。

在 PHP 中,常量是绑定到某个值的标识符,该值在程序执行期间是不可变的。该值可以是任何对象或值。如果您有两个引用相同值的 PHP 常量,例如define("A", "value")define("B", "value"),那么这实际上是两个独立的标识符,指向两个唯一值。

因此,虽然AB 指向相同的语义内容,但它们并不指向单个可识别对象。而且它们不会通过引用它们来简化为单个可识别的对象。 PHP 中没有内部存储来保存常见符号到 ID 的映射,就像 ruby​​ 中的符号一样。所以我不会说红宝石符号完全等同于 PHP 常量。

[1] - https://ruby-doc.org/core-2.2.0/Symbol.html

【讨论】:

  • “大多数 ruby​​ 实现都保留了解释器内部的符号表。” - 几乎所有语言实现都有类似的东西,包括(我猜)大多数 PHP 实现(P8,栎属、桃派等)。不同之处在于 Ruby、Smalltalk、Lisp、Erlang、Elixir 等将其暴露给程序员。
  • @JörgWMittag 因为人类是编程事物的人......明白吗?
【解决方案2】:

他们之间没有任何关系。询问他们的差异就像询问丰田卡罗拉和蓝色之间的差异。

constant 是(作为第一个近似值)在初始化期间只能分配一次的变量。常量是对值的不可变引用

符号是代表“名称”(在编程语言意义上)、“标识符”(同样,在编程语言意义上)或“标签”概念的值。就像字符串是代表“文本”概念的值一样。符号是不可变的、直接的,并且它们会自行评估。

所以,符号是值,常量不是。 (常量是 值的引用)。符号对自己求值,常量根据它们引用的任何值求值。符号数据类型本质上向程序员公开了大多数语言实现(包括 Peachpie、P8、Quercus 和其他 PHP 实现)具有但通常不公开的东西:符号表。符号并不是 Ruby 独有的,它们也存在于 Smalltalk(Ruby 从中获取符号)、Newspeak、Self、大多数 Lisps(包括 Clojure、Scheme、CommonLisp)、Elixir、Erlang、ECMAScript、Scala 和许多其他语言中。

【讨论】:

    猜你喜欢
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多