ruby - Ruby 中的浮点值是立即数吗?
问题描述
根据Ruby FAQ,fixnum
(hold integer
)boolean
和nil
是立即值。在我的理解中,一个拥有立即数的对象总是完全相同的,不管它被分配了多少个变量。这在 Ruby 中很容易验证:
# Immediate values
i1 = 1
i2 = 1
i1.object_id # the same as i2's id
i2.object_id # the same as i1's id
# Not immediate values
s1 = "1"
s2 = "1"
s1.object_id # NOT the same as s2's id
s2.object_id # NOT the same as s1's id
float
似乎也是即时值:
f1 = 2.1
f2 = 2.1
f1.object_id # the same as f2's id
f2.object_id # the same as f1's id
但是,我找不到任何float
直接值的参考。Ruby 中的浮点值是立即数吗?如何float
在 Ruby 中工作?
解决方案
Ruby 中不存在立即值的概念
现在,您可能会问“当Ruby没有立即值时,为什么Ruby常见问题解答谈论立即值?” 这个问题的答案是,不幸的是,Ruby 社区中的许多文档混淆了称为“Ruby”的编程语言的概念和许多 Ruby 实现之一,不幸的是,它也经常被称为“Ruby”,尽管它“官方”名称是“ YARV ”。
例如,如果您查看ISO/IEC 30170:2012信息技术 — 编程语言 — Ruby规范,您将发现没有提及立即值,无论是在该名称下,还是在任何其他名称下的类似概念。它们根本不存在。
另请注意有关链接到的立即值部分中的以下警告:
此部分或部分内容可能已过时或需要确认。
所以,我们有两个问题:
- 本节仅讨论Ruby 的一个特定实现,在众多实现中,但并没有说明这一点,并且
- 甚至特定于实现的信息也已过时。
在当前版本的 YARV 中,Fixnum
不再存在。过去,Integer
是一个具有两个具体子类的抽象类:Fixnum
和Bignum
. Fixnum
s 是直接值,Bignum
s 不是。
但是,根据您是在 32 位还是 64 位中运行,完全相同的文字可能是 a Fixnum
,即立即数,或者是 a Bignum
。32 位Fixnum
可以存储 31 位,64 位Fixnum
可以存储 63 位。请注意,这仅适用于 YARV,不过,例如JRuby将在32 位和 64 位平台上存储 64 位(不仅是 63 位) 。
如今,Fixnum
并Bignum
不再存在,并且Integer
是一个具体的类,而不是一个抽象的类。但是,实际上优化还在进行中:YARV在 32 位系统上仍然优化 31 位Integer
为fixnumInteger
,在 64 位系统上优化为 63 位,JRuby仍然优化 64 位Integer
。
JRuby 优化Float
s 已经很长时间了。在 JRuby 中,Float
s 是立即数。然而,在 YARV 中,没有这样的优化。Float
s 不是直接值。然而,最近,YARV 引入了flonum的概念。Flonum是Float
适合 62 位的 s。Flonum是立即数。此外,此优化仅在 64 位平台上执行,在 32 位平台上完全禁用flonum 。
另请注意,FAQ 完全忽略了Symbol
在许多实现(包括 YARV)中是立即值的 s。
所以,回答你的问题:
Ruby 中的浮点值是立即数吗?
不,也许。其中一些,有时。
不,Float
s 不是 Ruby 中的直接值,如果“Ruby”是指“Ruby 编程语言”。Ruby语言没有立即值的概念。
也许,Float
s 是 Ruby 中的直接值,也许不是,如果“Ruby”是指“所有现有 Ruby 实现的集合”。在某些实现中,在某些情况下,某些Float
值可能是也可能不是立即值。
有些Float
s 有时是直接值,如果“Ruby”是指“YARV”。在 64 位平台上,Float
s 的一个子集是立即数,但不是全部。在 32 位平台上,没有一个是立即数。
这无关紧要
你只能通过改变它来判断一个值是否是立即的。但是,执行此类优化的所有值都是不可变的,不能有实例变量,也不能有单例方法或单例类。
因此,实际上不可能判断某物是否是直接值。这是一个私有的内部优化细节。
这意味着您可以完全忽略该概念,因为它无法使您的程序以不同的方式运行。
怎么样object_id
?
首先:Object#object_id
是可憎的。它不应该存在。只需忘记您曾经听说过它。
它违反了面向对象的基本原则之一,即模拟另一个对象的对象应该与该对象无法区分。(同样适用于BasicObject#equal?
。)
但其次,这是一个反例:
# frozen_string_literal: true
# Not immediate values
s1 = '1'
s2 = '1'
s1.object_id
#=> 60
# SAME as `s2`'s id
s2.object_id
#=> 60
# SAME as `s1`'s id
哎呀。我打破了你的测试:冻结String
文字不是直接对象,但它们会自动重复数据删除。
推荐阅读
- angular - ionic 3 [object object] 无法在 Android P 中解析数据
- django - 如何在 Python 中访问动态生成的元组?
- java - 为什么当我打开我的应用程序时没有出现默认选项卡?
- java - 为什么这两个代码片段没有给出相同的输出?
- c - 指向二维字符数组的指针:一步或两步的声明和初始化
- snowflake-cloud-data-platform - 如何限制重复记录插入到雪花表中
- java - 我的应用程序在我启动和启动时崩溃了?
- ignite - Apache Ignite org.apache.ignite.IgniteCheckedException:握手消息无效
- python - jupyter notebook/lab终端python版
- browser - 如何通过将一些参数传递到 URL 来打开新选项卡