types - 如果无法在编译时确定,如何检测 Crystal 中的数据类型?
问题描述
我正在为以太坊 RLP标准用水晶语言编写递归编码器。
我要做的是获取任何要编码的传入数据块并确定它的类型。现在,为了简单起见,我可以忽略无效类型。
RLP 编码的有效类型是二进制Bytes
、字符串String
或字符串列表Array(String)
。到目前为止,一切都很好,我写了三个方法来支持三种数据类型:
module Rlp
# rlp-encodes binary data
def self.encode(b : Bytes)
return "binary #{typeof(b)} #{b}"
end
# rlp-encodes lists data
def self.encode(l : Array(String))
return "listsy #{typeof(l)} #{l}"
end
# rlp-encodes string data
def self.encode(s : String)
return "strngy #{typeof(s)} #{s}"
end
end
然而,现在这里有一些深度,因为数组可以嵌套。因此,这个编码器是递归的。给定 anArray(String)
它给它一些前缀并String
用 with编码Rlp.encode(s : String)
。现在,拥有嵌套数组的逻辑是.encode
根据需要经常调用来编码所有内容。但是,我没有想到如何在编译时确定类型。
例如:
79 | Rlp.encode([["a", "b", "c"], ["cow", "dog", "cat"]])
^-----
Error: no overload matches 'Rlp.encode' with type Array(Array(String))
对,因为我没有任何self.encode(l : Array(Array(String)))
实现,而且我无法知道此处的嵌套深度以可能实现所有可能的情况。
我尝试实现self.encode(data)
不指定数据类型的不太严格的包装器方法,但是,我基本上无能为力,data
因为编译器根据我的用法暗示数据类型,即:
# rlp-encodes _any_ data
def self.encode(data)
if typeof(data) == Int32
return Bytes.new data
elsif typeof(data) == Char
return String.new data
end
end
传递32
类型Int32
会导致:
45 | return String.new data
Error: no overload matches 'String.new' with type Int32
即使不会使用 type 的数据调用此代码Int32
。我不知道如何在这里进行。无论如何,在编译时不可知论者使用的类型是否更聪明?
理想情况下,我会接受任何数据作为输入并自己处理不同的情况。
解决方案
如果您Rlp.encode
按如下方式声明 for Array,编译器将负责为不同类型的数组实例化该方法。
module Rlp
# rlp-encodes lists data
def self.encode(l : Array)
return "listsy #{typeof(l)} #{l}"
end
end
推荐阅读
- django - 与 Django-Rest-Framework 中的 PrimaryKeyRelatedField 相关时获取列而不是对象
- wordpress - 如何在 wordpress 中将自定义按钮添加到我的 tinyMCE
- push-notification - 为什么服务人员在取消订阅并再次订阅后不工作
- c - 如何在 PSoC Creator 中使用 PSoC 5LP 创建 100 毫秒的内部 RTC 定时器中断而不使 PSoC 休眠?
- rollup - 汇总监视包含目录
- javascript - 即使 Package.json 有 ""start": "set PORT=3500 && react-scripts start"",带有 React-Service 的 Docker-compose 总是选择 PORT 3000
- c++ - JsonCpp:如何将对象转换/序列化为 Json::Value
- css - SCSS 编译从 css 中删除 -webkit 和 -ms 属性
- obiee - OBIEE:通过 Direct Query 分析执行的过程运行两次。为什么
- javascript - 如何在屏幕锁定或最小化浏览器期间禁用移动设备上的网页音频?