Crystal语言:在运行时String :: to_sym之外使用什么代替

6

我正在尝试将一个Ruby程序转换为Crystal。

但是我卡在了缺少string.to_sym的地方。

我有一个非常大的XML文件,它太大而无法放入内存。

因此,完全解析它是不可能的。幸运的是,我不需要所有信息,只需要其中一部分。所以我自己对其进行解析,放弃大部分的行。我使用 String::to_sym 来存储数据,就像这样:

:param_name1 => 1
:param_name2 => 11
:param_name1 => 2
:param_name2 => 22
:param_name1 => 3
:param_name2 => 33

在Crystal中应该使用什么?

内存是瓶颈。我不想多次存储param_name1

1个回答

7
如果您有一个已知的参数列表,例如可以使用枚举类型:
enum Parameter
  Name1
  Name2
  Name3
end

a = "Name1"
b = {'N', 'a', 'm', 'e', '1'}.join
pp a.object_id == b.object_id # => false
pp Parameter.parse(a) == Parameter.parse(b) # => true

如果参数列表未知,您可以使用效率较低的StringPool:
require "string_pool"

pool = StringPool.new

a = "param1"
b = {'p', 'a', 'r', 'a', 'm', '1'}.join

pp a.object_id == b.object_id # => false
a = pool.get(a)
b = pool.get(b)
pp a.object_id == b.object_id # => true

我有点困惑,因为在编译时Crystal具有不可变的字符串和符号,但我看不出两者之间的区别。还有枚举类型。只有枚举类型可以在运行时使用(从名称获取int32)。StringPool是Symbol的运行时等效吗? - jsaak
符号在编译时被翻译成唯一的数字,因此它们的内存表示是一个单一的数字。这就是为什么你不能动态地创建它们,值在编译时被非确定性地分配,表在运行时无法扩展的原因。 - Jonne Haß
字符串是不可变的,但它们的完整数据存储在内存中,因此您可以对其实际字符串值执行操作。符号必须先转换为其字符串值才能这样做。StringPool仅是一个方便的API,它使用查找哈希/集合来去重实例。 - Jonne Haß
枚举类型更接近于符号,但命名空间和每个自己的类型实例也是如此。同样,您无法在运行时扩展其值集。作为一种类型,允许向其中添加方法,例如信号API就像Signal :: INT.trap {...}一样使用它。它还允许轻松地在编译时生成“解析”方法:https://github.com/manastech/crystal/blob/master/src/enum.cr#L323-L332 - Jonne Haß

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接