首页 > 解决方案 > 如果无法在编译时确定,如何检测 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。我不知道如何在这里进行。无论如何,在编译时不可知论者使用的类型是否更聪明?

理想情况下,我会接受任何数据作为输入并自己处理不同的情况。

标签: typesconditional-statementsethereumcompile-timecrystal-lang

解决方案


如果您Rlp.encode按如下方式声明 for Array,编译器将负责为不同类型的数组实例化该方法。

module Rlp
  # rlp-encodes lists data
  def self.encode(l : Array)
    return "listsy #{typeof(l)} #{l}"
  end
end

推荐阅读